From ac28731d11c108550eedf295d0f3d55c708db46d Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Fri, 5 Apr 2019 15:56:06 +0200 Subject: [PATCH] gateway: only admin or the same logged user can create an user token --- internal/services/gateway/api/user.go | 21 +++++------ internal/services/gateway/command/user.go | 45 +++++++++++++++++++++++ internal/services/gateway/gateway.go | 2 +- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/internal/services/gateway/api/user.go b/internal/services/gateway/api/user.go index c559393..19f2ff4 100644 --- a/internal/services/gateway/api/user.go +++ b/internal/services/gateway/api/user.go @@ -59,6 +59,7 @@ func (h *CreateUserHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { u, err := h.ch.CreateUser(ctx, creq) if httpError(w, err) { + h.log.Errorf("err: %+v", err) return } @@ -68,7 +69,6 @@ func (h *CreateUserHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - } type DeleteUserHandler struct { @@ -375,12 +375,12 @@ type CreateUserTokenResponse struct { } type CreateUserTokenHandler struct { - log *zap.SugaredLogger - configstoreClient *csapi.Client + log *zap.SugaredLogger + ch *command.CommandHandler } -func NewCreateUserTokenHandler(logger *zap.Logger, configstoreClient *csapi.Client) *CreateUserTokenHandler { - return &CreateUserTokenHandler{log: logger.Sugar(), configstoreClient: configstoreClient} +func NewCreateUserTokenHandler(logger *zap.Logger, ch *command.CommandHandler) *CreateUserTokenHandler { + return &CreateUserTokenHandler{log: logger.Sugar(), ch: ch} } func (h *CreateUserTokenHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -395,20 +395,19 @@ func (h *CreateUserTokenHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques return } - creq := &csapi.CreateUserTokenRequest{ + creq := &command.CreateUserTokenRequest{ + UserName: userName, TokenName: req.TokenName, } h.log.Infof("creating user %q token", userName) - cresp, _, err := h.configstoreClient.CreateUserToken(ctx, userName, creq) - if err != nil { + token, err := h.ch.CreateUserToken(ctx, creq) + if httpError(w, err) { h.log.Errorf("err: %+v", err) - http.Error(w, err.Error(), http.StatusInternalServerError) return } - h.log.Infof("user %q token created", userName) resp := &CreateUserTokenResponse{ - Token: cresp.Token, + Token: token, } if err := json.NewEncoder(w).Encode(resp); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/internal/services/gateway/command/user.go b/internal/services/gateway/command/user.go index 7ef8ce9..08b1220 100644 --- a/internal/services/gateway/command/user.go +++ b/internal/services/gateway/command/user.go @@ -54,6 +54,51 @@ func (c *CommandHandler) CreateUser(ctx context.Context, req *CreateUserRequest) return u, nil } +type CreateUserTokenRequest struct { + UserName string + TokenName string +} + +func (c *CommandHandler) CreateUserToken(ctx context.Context, req *CreateUserTokenRequest) (string, error) { + var userID string + userIDVal := ctx.Value("userid") + if userIDVal != nil { + userID = userIDVal.(string) + } + + isAdmin := false + isAdminVal := ctx.Value("admin") + if isAdminVal != nil { + isAdmin = isAdminVal.(bool) + } + + userName := req.UserName + user, _, err := c.configstoreClient.GetUserByName(ctx, userName) + if err != nil { + return "", errors.Wrapf(err, "failed to get user %q", userID) + } + + // only admin or the same logged user can create a token + if !isAdmin && user.ID != userID { + return "", util.NewErrBadRequest(errors.Errorf("logged in user cannot create token for another user")) + } + if _, ok := user.Tokens[req.TokenName]; ok { + return "", util.NewErrBadRequest(errors.Errorf("user %q already have a token with name %q", userName, req.TokenName)) + } + + c.log.Infof("creating user token") + creq := &csapi.CreateUserTokenRequest{ + TokenName: req.TokenName, + } + res, _, err := c.configstoreClient.CreateUserToken(ctx, userName, creq) + if err != nil { + return "", errors.Wrapf(err, "failed to create user token") + } + c.log.Infof("token %q for user %q created", req.TokenName, userName) + + return res.Token, nil +} + type CreateUserLARequest struct { UserName string RemoteSourceName string diff --git a/internal/services/gateway/gateway.go b/internal/services/gateway/gateway.go index 775d0f5..65280d0 100644 --- a/internal/services/gateway/gateway.go +++ b/internal/services/gateway/gateway.go @@ -174,7 +174,7 @@ func (g *Gateway) Run(ctx context.Context) error { createUserLAHandler := api.NewCreateUserLAHandler(logger, g.ch) deleteUserLAHandler := api.NewDeleteUserLAHandler(logger, g.configstoreClient) - createUserTokenHandler := api.NewCreateUserTokenHandler(logger, g.configstoreClient) + createUserTokenHandler := api.NewCreateUserTokenHandler(logger, g.ch) deleteUserTokenHandler := api.NewDeleteUserTokenHandler(logger, g.configstoreClient) remoteSourceHandler := api.NewRemoteSourceHandler(logger, g.configstoreClient)