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
|
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) {
|
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)
|
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 {
|
type DeleteUserHandler struct {
|
||||||
log *zap.SugaredLogger
|
log *zap.SugaredLogger
|
||||||
ch *command.CommandHandler
|
ch *command.CommandHandler
|
||||||
|
|
|
@ -180,6 +180,20 @@ func (s *CommandHandler) CreateProject(ctx context.Context, project *types.Proje
|
||||||
if pg != nil {
|
if pg != nil {
|
||||||
return util.NewErrBadRequest(errors.Errorf("project group with name %q, path %q already exists", pg.Name, pp))
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -407,6 +421,76 @@ func (s *CommandHandler) DeleteUser(ctx context.Context, userName string) error
|
||||||
return err
|
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 {
|
type CreateUserLARequest struct {
|
||||||
UserName string
|
UserName string
|
||||||
RemoteSourceName string
|
RemoteSourceName string
|
||||||
|
|
|
@ -145,6 +145,7 @@ func (s *ConfigStore) Run(ctx context.Context) error {
|
||||||
usersHandler := api.NewUsersHandler(logger, s.readDB)
|
usersHandler := api.NewUsersHandler(logger, s.readDB)
|
||||||
userByNameHandler := api.NewUserByNameHandler(logger, s.readDB)
|
userByNameHandler := api.NewUserByNameHandler(logger, s.readDB)
|
||||||
createUserHandler := api.NewCreateUserHandler(logger, s.ch)
|
createUserHandler := api.NewCreateUserHandler(logger, s.ch)
|
||||||
|
updateUserHandler := api.NewUpdateUserHandler(logger, s.ch)
|
||||||
deleteUserHandler := api.NewDeleteUserHandler(logger, s.ch)
|
deleteUserHandler := api.NewDeleteUserHandler(logger, s.ch)
|
||||||
|
|
||||||
createUserLAHandler := api.NewCreateUserLAHandler(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", usersHandler).Methods("GET")
|
||||||
apirouter.Handle("/users", createUserHandler).Methods("POST")
|
apirouter.Handle("/users", createUserHandler).Methods("POST")
|
||||||
apirouter.Handle("/users/{username}", userByNameHandler).Methods("GET")
|
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}", deleteUserHandler).Methods("DELETE")
|
||||||
|
|
||||||
apirouter.Handle("/users/{username}/linkedaccounts", createUserLAHandler).Methods("POST")
|
apirouter.Handle("/users/{username}/linkedaccounts", createUserLAHandler).Methods("POST")
|
||||||
|
|
Loading…
Reference in New Issue