apigen: endpoint to get user

Implemented new GET user by request context endpoint.
Updated docs.

Change-Id: Iebb493e55f9456b89d7dbd234bb0b939b82b0ced
This commit is contained in:
Vitalii 2022-05-27 17:31:28 +03:00 committed by Storj Robot
parent ba58530089
commit f0b28d6326
6 changed files with 185 additions and 44 deletions

View File

@ -23,6 +23,7 @@ const dateLayout = "2006-01-02T15:04:05.000Z"
var ErrProjectsAPI = errs.Class("consoleapi projects api")
var ErrApikeysAPI = errs.Class("consoleapi apikeys api")
var ErrUsersAPI = errs.Class("consoleapi users api")
type ProjectManagementService interface {
GenGetUsersProjects(context.Context) ([]console.Project, api.HTTPError)
@ -36,6 +37,10 @@ type APIKeyManagementService interface {
GenCreateAPIKey(context.Context, console.CreateAPIKeyRequest) (*console.CreateAPIKeyResponse, api.HTTPError)
}
type UserManagementService interface {
GenGetUser(context.Context) (*console.ResponseUser, api.HTTPError)
}
// ProjectManagementHandler is an api handler that exposes all projects related functionality.
type ProjectManagementHandler struct {
log *zap.Logger
@ -50,6 +55,13 @@ type APIKeyManagementHandler struct {
auth api.Auth
}
// UserManagementHandler is an api handler that exposes all users related functionality.
type UserManagementHandler struct {
log *zap.Logger
service UserManagementService
auth api.Auth
}
func NewProjectManagement(log *zap.Logger, service ProjectManagementService, router *mux.Router, auth api.Auth) *ProjectManagementHandler {
handler := &ProjectManagementHandler{
log: log,
@ -58,11 +70,11 @@ func NewProjectManagement(log *zap.Logger, service ProjectManagementService, rou
}
projectsRouter := router.PathPrefix("/api/v0/projects").Subrouter()
projectsRouter.HandleFunc("/bucket-rollup", handler.handleGenGetSingleBucketUsageRollup).Methods("GET")
projectsRouter.HandleFunc("/bucket-rollups", handler.handleGenGetBucketUsageRollups).Methods("GET")
projectsRouter.HandleFunc("/create", handler.handleGenCreateProject).Methods("POST")
projectsRouter.HandleFunc("/update/{id}", handler.handleGenUpdateProject).Methods("PATCH")
projectsRouter.HandleFunc("/", handler.handleGenGetUsersProjects).Methods("GET")
projectsRouter.HandleFunc("/bucket-rollup", handler.handleGenGetSingleBucketUsageRollup).Methods("GET")
return handler
}
@ -80,6 +92,62 @@ func NewAPIKeyManagement(log *zap.Logger, service APIKeyManagementService, route
return handler
}
func NewUserManagement(log *zap.Logger, service UserManagementService, router *mux.Router, auth api.Auth) *UserManagementHandler {
handler := &UserManagementHandler{
log: log,
service: service,
auth: auth,
}
usersRouter := router.PathPrefix("/api/v0/users").Subrouter()
usersRouter.HandleFunc("/", handler.handleGenGetUser).Methods("GET")
return handler
}
func (h *ProjectManagementHandler) handleGenGetBucketUsageRollups(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set("Content-Type", "application/json")
ctx, err = h.auth.IsAuthenticated(ctx, r, true, true)
if err != nil {
api.ServeError(h.log, w, http.StatusUnauthorized, err)
return
}
projectID, err := uuid.FromString(r.URL.Query().Get("projectID"))
if err != nil {
api.ServeError(h.log, w, http.StatusBadRequest, err)
return
}
since, err := time.Parse(dateLayout, r.URL.Query().Get("since"))
if err != nil {
api.ServeError(h.log, w, http.StatusBadRequest, err)
return
}
before, err := time.Parse(dateLayout, r.URL.Query().Get("before"))
if err != nil {
api.ServeError(h.log, w, http.StatusBadRequest, err)
return
}
retVal, httpErr := h.service.GenGetBucketUsageRollups(ctx, projectID, since, before)
if httpErr.Err != nil {
api.ServeError(h.log, w, httpErr.Status, httpErr.Err)
return
}
err = json.NewEncoder(w).Encode(retVal)
if err != nil {
h.log.Debug("failed to write json GenGetBucketUsageRollups response", zap.Error(ErrProjectsAPI.Wrap(err)))
}
}
func (h *ProjectManagementHandler) handleGenCreateProject(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -228,49 +296,6 @@ func (h *ProjectManagementHandler) handleGenGetSingleBucketUsageRollup(w http.Re
}
}
func (h *ProjectManagementHandler) handleGenGetBucketUsageRollups(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set("Content-Type", "application/json")
ctx, err = h.auth.IsAuthenticated(ctx, r, true, true)
if err != nil {
api.ServeError(h.log, w, http.StatusUnauthorized, err)
return
}
projectID, err := uuid.FromString(r.URL.Query().Get("projectID"))
if err != nil {
api.ServeError(h.log, w, http.StatusBadRequest, err)
return
}
since, err := time.Parse(dateLayout, r.URL.Query().Get("since"))
if err != nil {
api.ServeError(h.log, w, http.StatusBadRequest, err)
return
}
before, err := time.Parse(dateLayout, r.URL.Query().Get("before"))
if err != nil {
api.ServeError(h.log, w, http.StatusBadRequest, err)
return
}
retVal, httpErr := h.service.GenGetBucketUsageRollups(ctx, projectID, since, before)
if httpErr.Err != nil {
api.ServeError(h.log, w, httpErr.Status, httpErr.Err)
return
}
err = json.NewEncoder(w).Encode(retVal)
if err != nil {
h.log.Debug("failed to write json GenGetBucketUsageRollups response", zap.Error(ErrProjectsAPI.Wrap(err)))
}
}
func (h *APIKeyManagementHandler) handleGenCreateAPIKey(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -301,3 +326,28 @@ func (h *APIKeyManagementHandler) handleGenCreateAPIKey(w http.ResponseWriter, r
h.log.Debug("failed to write json GenCreateAPIKey response", zap.Error(ErrApikeysAPI.Wrap(err)))
}
}
func (h *UserManagementHandler) handleGenGetUser(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set("Content-Type", "application/json")
ctx, err = h.auth.IsAuthenticated(ctx, r, true, true)
if err != nil {
api.ServeError(h.log, w, http.StatusUnauthorized, err)
return
}
retVal, httpErr := h.service.GenGetUser(ctx)
if httpErr.Err != nil {
api.ServeError(h.log, w, httpErr.Status, httpErr.Err)
return
}
err = json.NewEncoder(w).Encode(retVal)
if err != nil {
h.log.Debug("failed to write json GenGetUser response", zap.Error(ErrUsersAPI.Wrap(err)))
}
}

View File

@ -214,3 +214,29 @@ A successful response body:
}
}
```
### User Endpoints
#### GET /api/v0/users/
Returns User entity by request context.
A successful response body:
```json
{
"id": "00fe2cef-9412-4c9c-bc42-e57cc062bb7d",
"fullName": "Test",
"shortName": "",
"email": "test@test.com",
"partnerId": "00000000-0000-0000-0000-000000000000",
"userAgent": null,
"projectLimit": 1,
"isProfessional": false,
"position": "",
"companyName": "",
"employeeCount": "",
"haveSalesContact": false,
"paidTier": false,
"isMFAEnabled": false,
"mfaRecoveryCodeCount": 0
}
```

View File

@ -93,5 +93,16 @@ func main() {
})
}
{
g := a.Group("UserManagement", "users")
g.Get("/", &apigen.Endpoint{
Name: "Get User",
Description: "Gets User by request context",
MethodName: "GenGetUser",
Response: &console.ResponseUser{},
})
}
a.MustWriteGo("satellite/console/consoleweb/consoleapi/api.gen.go")
}

View File

@ -221,6 +221,7 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc
if server.config.GeneratedAPIEnabled {
consoleapi.NewProjectManagement(logger, server.service, router, server.service)
consoleapi.NewAPIKeyManagement(logger, server.service, router, server.service)
consoleapi.NewUserManagement(logger, server.service, router, server.service)
}
router.HandleFunc("/registrationToken/", server.createRegistrationTokenHandler)

View File

@ -1047,6 +1047,40 @@ func (s *Service) GetUser(ctx context.Context, id uuid.UUID) (u *User, err error
return user, nil
}
// GenGetUser returns ResponseUser by request context for generated api.
func (s *Service) GenGetUser(ctx context.Context) (*ResponseUser, api.HTTPError) {
var err error
defer mon.Task()(&ctx)(&err)
auth, err := s.getAuthAndAuditLog(ctx, "get user")
if err != nil {
return nil, api.HTTPError{
Status: http.StatusUnauthorized,
Err: Error.Wrap(err),
}
}
user := &ResponseUser{
ID: auth.User.ID,
FullName: auth.User.FullName,
ShortName: auth.User.ShortName,
Email: auth.User.Email,
PartnerID: auth.User.PartnerID,
UserAgent: auth.User.UserAgent,
ProjectLimit: auth.User.ProjectLimit,
IsProfessional: auth.User.IsProfessional,
Position: auth.User.Position,
CompanyName: auth.User.CompanyName,
EmployeeCount: auth.User.EmployeeCount,
HaveSalesContact: auth.User.HaveSalesContact,
PaidTier: auth.User.PaidTier,
MFAEnabled: auth.User.MFAEnabled,
MFARecoveryCodeCount: len(auth.User.MFARecoveryCodes),
}
return user, api.HTTPError{}
}
// GetUserID returns the User ID from the session.
func (s *Service) GetUserID(ctx context.Context) (id uuid.UUID, err error) {
defer mon.Task()(&ctx)(&err)

View File

@ -174,3 +174,22 @@ type User struct {
FailedLoginCount int `json:"failedLoginCount"`
LoginLockoutExpiration time.Time `json:"loginLockoutExpiration"`
}
// ResponseUser is an entity which describes db User and can be sent in response.
type ResponseUser struct {
ID uuid.UUID `json:"id"`
FullName string `json:"fullName"`
ShortName string `json:"shortName"`
Email string `json:"email"`
PartnerID uuid.UUID `json:"partnerId"`
UserAgent []byte `json:"userAgent"`
ProjectLimit int `json:"projectLimit"`
IsProfessional bool `json:"isProfessional"`
Position string `json:"position"`
CompanyName string `json:"companyName"`
EmployeeCount string `json:"employeeCount"`
HaveSalesContact bool `json:"haveSalesContact"`
PaidTier bool `json:"paidTier"`
MFAEnabled bool `json:"isMFAEnabled"`
MFARecoveryCodeCount int `json:"mfaRecoveryCodeCount"`
}