configstore: add update user
This commit is contained in:
parent
ab7e4b8a4b
commit
9349728997
|
@ -323,6 +323,17 @@ func (c *Client) CreateUser(ctx context.Context, req *CreateUserRequest) (*types
|
|||
return user, resp, err
|
||||
}
|
||||
|
||||
func (c *Client) UpdateUser(ctx context.Context, userID string, req *UpdateUserRequest) (*types.User, *http.Response, error) {
|
||||
reqj, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
user := new(types.User)
|
||||
resp, err := c.getParsedResponse(ctx, "PUT", fmt.Sprintf("/users/%s", userID), nil, jsonContent, bytes.NewReader(reqj), user)
|
||||
return user, resp, err
|
||||
}
|
||||
|
||||
func (c *Client) DeleteUser(ctx context.Context, userName string) (*http.Response, error) {
|
||||
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/users/%s", userName), nil, jsonContent, nil)
|
||||
}
|
||||
|
|
|
@ -152,6 +152,50 @@ func (h *CreateUserHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
type UpdateUserRequest struct {
|
||||
UserName string `json:"user_name"`
|
||||
|
||||
UpdateUserLARequest *UpdateUserLARequest `json:"create_user_la_request"`
|
||||
}
|
||||
|
||||
type UpdateUserHandler struct {
|
||||
log *zap.SugaredLogger
|
||||
ch *command.CommandHandler
|
||||
}
|
||||
|
||||
func NewUpdateUserHandler(logger *zap.Logger, ch *command.CommandHandler) *UpdateUserHandler {
|
||||
return &UpdateUserHandler{log: logger.Sugar(), ch: ch}
|
||||
}
|
||||
|
||||
func (h *UpdateUserHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
vars := mux.Vars(r)
|
||||
userID := vars["userid"]
|
||||
|
||||
var req *UpdateUserRequest
|
||||
d := json.NewDecoder(r.Body)
|
||||
if err := d.Decode(&req); err != nil {
|
||||
httpError(w, util.NewErrBadRequest(err))
|
||||
return
|
||||
}
|
||||
|
||||
creq := &command.UpdateUserRequest{
|
||||
UserID: userID,
|
||||
UserName: req.UserName,
|
||||
}
|
||||
|
||||
user, err := h.ch.UpdateUser(ctx, creq)
|
||||
if httpError(w, err) {
|
||||
h.log.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := httpResponse(w, http.StatusCreated, user); err != nil {
|
||||
h.log.Errorf("err: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
type DeleteUserHandler struct {
|
||||
log *zap.SugaredLogger
|
||||
ch *command.CommandHandler
|
||||
|
|
|
@ -180,6 +180,20 @@ func (s *CommandHandler) CreateProject(ctx context.Context, project *types.Proje
|
|||
if pg != nil {
|
||||
return util.NewErrBadRequest(errors.Errorf("project group with name %q, path %q already exists", pg.Name, pp))
|
||||
}
|
||||
|
||||
// check that the linked account matches the remote source
|
||||
user, err := s.readDB.GetUserByLinkedAccount(tx, project.LinkedAccountID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get user with linked account id %q", project.LinkedAccountID)
|
||||
}
|
||||
la, ok := user.LinkedAccounts[project.LinkedAccountID]
|
||||
if !ok {
|
||||
return util.NewErrBadRequest(errors.Errorf("linked account id %q for user %q doesn't exist", project.LinkedAccountID, user.Name))
|
||||
}
|
||||
if la.RemoteSourceID != project.RemoteSourceID {
|
||||
return util.NewErrBadRequest(errors.Errorf("linked account id %q remote source %q different than project remote source %q", project.LinkedAccountID, la.RemoteSourceID, project.RemoteSourceID))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -407,6 +421,76 @@ func (s *CommandHandler) DeleteUser(ctx context.Context, userName string) error
|
|||
return err
|
||||
}
|
||||
|
||||
type UpdateUserRequest struct {
|
||||
UserID string
|
||||
|
||||
UserName string
|
||||
}
|
||||
|
||||
func (s *CommandHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest) (*types.User, error) {
|
||||
var cgt *datamanager.ChangeGroupsUpdateToken
|
||||
|
||||
cgNames := []string{}
|
||||
var user *types.User
|
||||
|
||||
// must do all the check in a single transaction to avoid concurrent changes
|
||||
err := s.readDB.Do(func(tx *db.Tx) error {
|
||||
var err error
|
||||
user, err = s.readDB.GetUserByName(tx, req.UserName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if user == nil {
|
||||
return util.NewErrBadRequest(errors.Errorf("user %q doesn't exist", req.UserName))
|
||||
}
|
||||
|
||||
cgt, err = s.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if req.UserName != "" {
|
||||
// check duplicate user name
|
||||
u, err := s.readDB.GetUserByName(tx, req.UserName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if u != nil {
|
||||
return util.NewErrBadRequest(errors.Errorf("user with name %q already exists", u.Name))
|
||||
}
|
||||
// changegroup is the username (and in future the email) to ensure no
|
||||
// concurrent user creation/modification using the same name
|
||||
cgNames = append(cgNames, util.EncodeSha256Hex("username-"+req.UserName))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.UserName != "" {
|
||||
user.Name = req.UserName
|
||||
}
|
||||
|
||||
userj, err := json.Marshal(user)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to marshal user")
|
||||
}
|
||||
|
||||
actions := []*datamanager.Action{
|
||||
{
|
||||
ActionType: datamanager.ActionTypePut,
|
||||
DataType: string(types.ConfigTypeUser),
|
||||
ID: user.ID,
|
||||
Data: userj,
|
||||
},
|
||||
}
|
||||
|
||||
_, err = s.dm.WriteWal(ctx, actions, cgt)
|
||||
return user, err
|
||||
}
|
||||
|
||||
type CreateUserLARequest struct {
|
||||
UserName string
|
||||
RemoteSourceName string
|
||||
|
|
|
@ -145,6 +145,7 @@ func (s *ConfigStore) Run(ctx context.Context) error {
|
|||
usersHandler := api.NewUsersHandler(logger, s.readDB)
|
||||
userByNameHandler := api.NewUserByNameHandler(logger, s.readDB)
|
||||
createUserHandler := api.NewCreateUserHandler(logger, s.ch)
|
||||
updateUserHandler := api.NewUpdateUserHandler(logger, s.ch)
|
||||
deleteUserHandler := api.NewDeleteUserHandler(logger, s.ch)
|
||||
|
||||
createUserLAHandler := api.NewCreateUserLAHandler(logger, s.ch)
|
||||
|
@ -196,6 +197,7 @@ func (s *ConfigStore) Run(ctx context.Context) error {
|
|||
apirouter.Handle("/users", usersHandler).Methods("GET")
|
||||
apirouter.Handle("/users", createUserHandler).Methods("POST")
|
||||
apirouter.Handle("/users/{username}", userByNameHandler).Methods("GET")
|
||||
apirouter.Handle("/users/{userid}", updateUserHandler).Methods("PUT")
|
||||
apirouter.Handle("/users/{username}", deleteUserHandler).Methods("DELETE")
|
||||
|
||||
apirouter.Handle("/users/{username}/linkedaccounts", createUserLAHandler).Methods("POST")
|
||||
|
|
Loading…
Reference in New Issue