configstore: createuser also create linked account when requested
Useful to future user registration to create user and linked account in a unique atomic call.
This commit is contained in:
parent
3e3a7a0ea5
commit
704da47afc
|
@ -314,14 +314,14 @@ func (c *Client) GetUserByLinkedAccount(ctx context.Context, linkedAccountID str
|
|||
return users[0], resp, err
|
||||
}
|
||||
|
||||
func (c *Client) CreateUser(ctx context.Context, user *types.User) (*types.User, *http.Response, error) {
|
||||
uj, err := json.Marshal(user)
|
||||
func (c *Client) CreateUser(ctx context.Context, req *CreateUserRequest) (*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", "/users", nil, jsonContent, bytes.NewReader(uj), user)
|
||||
user := new(types.User)
|
||||
resp, err := c.getParsedResponse(ctx, "PUT", "/users", nil, jsonContent, bytes.NewReader(reqj), user)
|
||||
return user, resp, err
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,12 @@ func (h *UserByNameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
type CreateUserRequest struct {
|
||||
UserName string `json:"user_name"`
|
||||
|
||||
CreateUserLARequest *CreateUserLARequest `json:"create_user_la_request"`
|
||||
}
|
||||
|
||||
type CreateUserHandler struct {
|
||||
log *zap.SugaredLogger
|
||||
ch *command.CommandHandler
|
||||
|
@ -115,14 +121,28 @@ func NewCreateUserHandler(logger *zap.Logger, ch *command.CommandHandler) *Creat
|
|||
func (h *CreateUserHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
var req types.User
|
||||
var req *CreateUserRequest
|
||||
d := json.NewDecoder(r.Body)
|
||||
if err := d.Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := h.ch.CreateUser(ctx, &req)
|
||||
creq := &command.CreateUserRequest{
|
||||
UserName: req.UserName,
|
||||
}
|
||||
if req.CreateUserLARequest != nil {
|
||||
creq.CreateUserLARequest = &command.CreateUserLARequest{
|
||||
RemoteSourceName: req.CreateUserLARequest.RemoteSourceName,
|
||||
RemoteUserID: req.CreateUserLARequest.RemoteUserID,
|
||||
RemoteUserName: req.CreateUserLARequest.RemoteUserName,
|
||||
Oauth2AccessToken: req.CreateUserLARequest.Oauth2AccessToken,
|
||||
Oauth2RefreshToken: req.CreateUserLARequest.Oauth2RefreshToken,
|
||||
UserAccessToken: req.CreateUserLARequest.UserAccessToken,
|
||||
}
|
||||
}
|
||||
|
||||
user, err := h.ch.CreateUser(ctx, creq)
|
||||
if httpError(w, err) {
|
||||
h.log.Errorf("err: %+v", err)
|
||||
return
|
||||
|
|
|
@ -239,13 +239,20 @@ func (s *CommandHandler) DeleteProject(ctx context.Context, projectRef string) e
|
|||
return err
|
||||
}
|
||||
|
||||
func (s *CommandHandler) CreateUser(ctx context.Context, user *types.User) (*types.User, error) {
|
||||
if user.UserName == "" {
|
||||
type CreateUserRequest struct {
|
||||
UserName string
|
||||
|
||||
CreateUserLARequest *CreateUserLARequest
|
||||
}
|
||||
|
||||
func (s *CommandHandler) CreateUser(ctx context.Context, req *CreateUserRequest) (*types.User, error) {
|
||||
if req.UserName == "" {
|
||||
return nil, util.NewErrBadRequest(errors.Errorf("user name required"))
|
||||
}
|
||||
|
||||
var cgt *wal.ChangeGroupsUpdateToken
|
||||
cgNames := []string{user.UserName}
|
||||
cgNames := []string{req.UserName}
|
||||
var rs *types.RemoteSource
|
||||
|
||||
// must do all the check in a single transaction to avoid concurrent changes
|
||||
err := s.readDB.Do(func(tx *db.Tx) error {
|
||||
|
@ -256,20 +263,58 @@ func (s *CommandHandler) CreateUser(ctx context.Context, user *types.User) (*typ
|
|||
}
|
||||
|
||||
// check duplicate user name
|
||||
u, err := s.readDB.GetUserByName(tx, user.UserName)
|
||||
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.UserName))
|
||||
}
|
||||
|
||||
if req.CreateUserLARequest != nil {
|
||||
rs, err = s.readDB.GetRemoteSourceByName(tx, req.CreateUserLARequest.RemoteSourceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rs == nil {
|
||||
return util.NewErrBadRequest(errors.Errorf("remote source %q doesn't exist", req.CreateUserLARequest.RemoteSourceName))
|
||||
}
|
||||
user, err := s.readDB.GetUserByLinkedAccountRemoteUserIDandSource(tx, req.CreateUserLARequest.RemoteUserID, rs.ID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get user for remote user id %q and remote source %q", req.CreateUserLARequest.RemoteUserID, rs.ID)
|
||||
}
|
||||
if user != nil {
|
||||
return util.NewErrBadRequest(errors.Errorf("user for remote user id %q for remote source %q already exists", req.CreateUserLARequest.RemoteUserID, req.CreateUserLARequest.RemoteSourceName))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user.ID = uuid.NewV4().String()
|
||||
user := &types.User{
|
||||
ID: uuid.NewV4().String(),
|
||||
UserName: req.UserName,
|
||||
}
|
||||
if req.CreateUserLARequest != nil {
|
||||
if user.LinkedAccounts == nil {
|
||||
user.LinkedAccounts = make(map[string]*types.LinkedAccount)
|
||||
}
|
||||
|
||||
la := &types.LinkedAccount{
|
||||
ID: uuid.NewV4().String(),
|
||||
RemoteSourceID: rs.ID,
|
||||
RemoteUserID: req.CreateUserLARequest.RemoteUserID,
|
||||
RemoteUserName: req.CreateUserLARequest.RemoteUserName,
|
||||
UserAccessToken: req.CreateUserLARequest.UserAccessToken,
|
||||
Oauth2AccessToken: req.CreateUserLARequest.Oauth2AccessToken,
|
||||
Oauth2RefreshToken: req.CreateUserLARequest.Oauth2RefreshToken,
|
||||
}
|
||||
|
||||
user.LinkedAccounts[la.ID] = la
|
||||
}
|
||||
|
||||
userj, err := json.Marshal(user)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to marshal user")
|
||||
|
@ -392,6 +437,14 @@ func (s *CommandHandler) CreateUserLA(ctx context.Context, req *CreateUserLARequ
|
|||
if rs == nil {
|
||||
return util.NewErrBadRequest(errors.Errorf("remote source %q doesn't exist", req.RemoteSourceName))
|
||||
}
|
||||
|
||||
user, err := s.readDB.GetUserByLinkedAccountRemoteUserIDandSource(tx, req.RemoteUserID, rs.ID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get user for remote user id %q and remote source %q", req.RemoteUserID, rs.ID)
|
||||
}
|
||||
if user != nil {
|
||||
return util.NewErrBadRequest(errors.Errorf("user for remote user id %q for remote source %q already exists", req.RemoteUserID, req.RemoteSourceName))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -39,12 +39,12 @@ func (c *CommandHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
|
|||
return nil, errors.Errorf("invalid user name %q", req.UserName)
|
||||
}
|
||||
|
||||
u := &types.User{
|
||||
creq := &csapi.CreateUserRequest{
|
||||
UserName: req.UserName,
|
||||
}
|
||||
|
||||
c.log.Infof("creating user")
|
||||
u, _, err := c.configstoreClient.CreateUser(ctx, u)
|
||||
u, _, err := c.configstoreClient.CreateUser(ctx, creq)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create user")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue