satellite/{db,console}: support v2 app account set up
This change modifies the register endpoint handler to not require name for signups from the v2 app and adds a new endpoint for completing account information (e.g. name). This is to support the new signup and account setup flow of the v2 app. Issue: #6470 Change-Id: I256e1c804fcdbc8ce05aa82d6bc4b0263f55daa5
This commit is contained in:
parent
1ba314428f
commit
f749b8ff51
@ -52,7 +52,7 @@ func (server *Server) addUser(w http.ResponseWriter, r *http.Request) {
|
||||
SignupPromoCode: input.SignupPromoCode,
|
||||
}
|
||||
|
||||
err = user.IsValid()
|
||||
err = user.IsValid(false)
|
||||
if err != nil {
|
||||
sendJSONError(w, "user data is not valid",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
|
@ -331,6 +331,8 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
|
||||
SignupPromoCode: registerData.SignupPromoCode,
|
||||
ActivationCode: code,
|
||||
SignupId: requestID,
|
||||
// signup from the v2 app doesn't require name.
|
||||
AllowNoName: strings.Contains(r.Referer(), "v2"),
|
||||
},
|
||||
secret,
|
||||
)
|
||||
@ -579,6 +581,25 @@ func (a *Auth) UpdateAccount(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetupAccount updates user's full name and short name.
|
||||
func (a *Auth) SetupAccount(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
var err error
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
var updatedInfo console.SetUpAccountRequest
|
||||
|
||||
err = json.NewDecoder(r.Body).Decode(&updatedInfo)
|
||||
if err != nil {
|
||||
a.serveJSONError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = a.service.SetupAccount(ctx, updatedInfo); err != nil {
|
||||
a.serveJSONError(ctx, w, err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetAccount gets authorized user and take it's params.
|
||||
func (a *Auth) GetAccount(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
@ -305,6 +305,7 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc
|
||||
authRouter.Use(server.withCORS)
|
||||
authRouter.Handle("/account", server.withAuth(http.HandlerFunc(authController.GetAccount))).Methods(http.MethodGet, http.MethodOptions)
|
||||
authRouter.Handle("/account", server.withAuth(http.HandlerFunc(authController.UpdateAccount))).Methods(http.MethodPatch, http.MethodOptions)
|
||||
authRouter.Handle("/account/setup", server.withAuth(http.HandlerFunc(authController.SetupAccount))).Methods(http.MethodPatch, http.MethodOptions)
|
||||
authRouter.Handle("/account/change-email", server.withAuth(http.HandlerFunc(authController.ChangeEmail))).Methods(http.MethodPost, http.MethodOptions)
|
||||
authRouter.Handle("/account/change-password", server.withAuth(server.userIDRateLimiter.Limit(http.HandlerFunc(authController.ChangePassword)))).Methods(http.MethodPost, http.MethodOptions)
|
||||
authRouter.Handle("/account/freezestatus", server.withAuth(http.HandlerFunc(authController.GetFreezeStatus))).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
@ -806,7 +806,7 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R
|
||||
captchaScore = score
|
||||
}
|
||||
|
||||
if err := user.IsValid(); err != nil {
|
||||
if err := user.IsValid(user.AllowNoName); err != nil {
|
||||
// NOTE: error is already wrapped with an appropriated class.
|
||||
return nil, err
|
||||
}
|
||||
@ -1492,6 +1492,36 @@ func (s *Service) UpdateAccount(ctx context.Context, fullName string, shortName
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetupAccount completes User's information.
|
||||
func (s *Service) SetupAccount(ctx context.Context, requestData SetUpAccountRequest) (err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
user, err := s.getUserAndAuditLog(ctx, "update account")
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
// validate fullName
|
||||
err = ValidateFullName(requestData.FullName)
|
||||
if err != nil {
|
||||
return ErrValidation.Wrap(err)
|
||||
}
|
||||
|
||||
err = s.store.Users().Update(ctx, user.ID, UpdateUserRequest{
|
||||
FullName: &requestData.FullName,
|
||||
IsProfessional: &requestData.IsProfessional,
|
||||
Position: requestData.Position,
|
||||
CompanyName: requestData.CompanyName,
|
||||
EmployeeCount: requestData.EmployeeCount,
|
||||
})
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
// TODO: track setup account
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChangeEmail updates email for a given user.
|
||||
func (s *Service) ChangeEmail(ctx context.Context, newEmail string) (err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
@ -115,18 +115,24 @@ type CreateUser struct {
|
||||
SignupPromoCode string `json:"signupPromoCode"`
|
||||
ActivationCode string `json:"-"`
|
||||
SignupId string `json:"-"`
|
||||
AllowNoName bool `json:"-"`
|
||||
}
|
||||
|
||||
// IsValid checks CreateUser validity and returns error describing whats wrong.
|
||||
// The returned error has the class ErrValiation.
|
||||
func (user *CreateUser) IsValid() error {
|
||||
func (user *CreateUser) IsValid(allowNoName bool) error {
|
||||
errgrp := errs.Group{}
|
||||
|
||||
errgrp.Add(
|
||||
ValidateFullName(user.FullName),
|
||||
ValidateNewPassword(user.Password),
|
||||
)
|
||||
|
||||
if !allowNoName {
|
||||
errgrp.Add(
|
||||
ValidateFullName(user.FullName),
|
||||
)
|
||||
}
|
||||
|
||||
// validate email
|
||||
_, err := mail.ParseAddress(user.Email)
|
||||
errgrp.Add(err)
|
||||
@ -283,6 +289,12 @@ type UpdateUserRequest struct {
|
||||
FullName *string
|
||||
ShortName **string
|
||||
|
||||
Position *string
|
||||
CompanyName *string
|
||||
WorkingOn *string
|
||||
IsProfessional *bool
|
||||
EmployeeCount *string
|
||||
|
||||
Email *string
|
||||
PasswordHash []byte
|
||||
|
||||
@ -328,3 +340,13 @@ type UpsertUserSettingsRequest struct {
|
||||
PassphrasePrompt *bool
|
||||
OnboardingStep *string
|
||||
}
|
||||
|
||||
// SetUpAccountRequest holds data for completing account setup.
|
||||
type SetUpAccountRequest struct {
|
||||
FullName string `json:"fullName"`
|
||||
IsProfessional bool `json:"isProfessional"`
|
||||
Position *string `json:"position"`
|
||||
CompanyName *string `json:"companyName"`
|
||||
EmployeeCount *string `json:"employeeCount"`
|
||||
StorageNeeds *string `json:"storageNeeds"`
|
||||
}
|
||||
|
@ -630,6 +630,19 @@ func toUpdateUser(request console.UpdateUserRequest) (*dbx.User_Update_Fields, e
|
||||
update.SignupId = dbx.User_SignupId(*request.SignupId)
|
||||
}
|
||||
|
||||
if request.IsProfessional != nil {
|
||||
update.IsProfessional = dbx.User_IsProfessional(*request.IsProfessional)
|
||||
}
|
||||
if request.Position != nil {
|
||||
update.Position = dbx.User_Position(*request.Position)
|
||||
}
|
||||
if request.CompanyName != nil {
|
||||
update.CompanyName = dbx.User_CompanyName(*request.CompanyName)
|
||||
}
|
||||
if request.EmployeeCount != nil {
|
||||
update.EmployeeCount = dbx.User_EmployeeCount(*request.EmployeeCount)
|
||||
}
|
||||
|
||||
return &update, nil
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,11 @@ func TestUpdateUser(t *testing.T) {
|
||||
FailedLoginCount: 1,
|
||||
LoginLockoutExpiration: time.Now().Truncate(time.Second),
|
||||
DefaultPlacement: 13,
|
||||
|
||||
IsProfessional: true,
|
||||
Position: "Engineer",
|
||||
CompanyName: "Storj",
|
||||
EmployeeCount: "1-200",
|
||||
}
|
||||
|
||||
require.NotEqual(t, u.FullName, newInfo.FullName)
|
||||
@ -104,6 +109,10 @@ func TestUpdateUser(t *testing.T) {
|
||||
require.NotEqual(t, u.FailedLoginCount, newInfo.FailedLoginCount)
|
||||
require.NotEqual(t, u.LoginLockoutExpiration, newInfo.LoginLockoutExpiration)
|
||||
require.NotEqual(t, u.DefaultPlacement, newInfo.DefaultPlacement)
|
||||
require.NotEqual(t, u.IsProfessional, newInfo.IsProfessional)
|
||||
require.NotEqual(t, u.Position, newInfo.Position)
|
||||
require.NotEqual(t, u.CompanyName, newInfo.CompanyName)
|
||||
require.NotEqual(t, u.EmployeeCount, newInfo.EmployeeCount)
|
||||
|
||||
// update just fullname
|
||||
updateReq := console.UpdateUserRequest{
|
||||
@ -304,6 +313,26 @@ func TestUpdateUser(t *testing.T) {
|
||||
|
||||
u.DefaultPlacement = newInfo.DefaultPlacement
|
||||
require.Equal(t, u, updatedUser)
|
||||
|
||||
// update professional info
|
||||
updateReq = console.UpdateUserRequest{
|
||||
IsProfessional: &newInfo.IsProfessional,
|
||||
Position: &newInfo.Position,
|
||||
CompanyName: &newInfo.CompanyName,
|
||||
EmployeeCount: &newInfo.EmployeeCount,
|
||||
}
|
||||
|
||||
err = users.Update(ctx, id, updateReq)
|
||||
require.NoError(t, err)
|
||||
|
||||
updatedUser, err = users.Get(ctx, id)
|
||||
require.NoError(t, err)
|
||||
|
||||
u.IsProfessional = newInfo.IsProfessional
|
||||
u.Position = newInfo.Position
|
||||
u.CompanyName = newInfo.CompanyName
|
||||
u.EmployeeCount = newInfo.EmployeeCount
|
||||
require.Equal(t, u, updatedUser)
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user