Implement user token delete
This commit is contained in:
parent
3a41e66f5b
commit
c4310be7de
|
@ -17,9 +17,9 @@ package cmd
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sorintlab/agola/internal/services/gateway/api"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -58,13 +58,13 @@ func userLADelete(cmd *cobra.Command, args []string) error {
|
|||
userName := userLADeleteOpts.userName
|
||||
laID := userLADeleteOpts.laID
|
||||
|
||||
log.Infof("deleting linked account %s for user %q", userName)
|
||||
log.Infof("deleting linked account %q for user %q", laID, userName)
|
||||
_, err := gwclient.DeleteUserLA(context.TODO(), userName, laID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to delete linked account")
|
||||
}
|
||||
|
||||
log.Infof("linked account %q for user %q deleted", userName, laID)
|
||||
log.Infof("linked account %q for user %q deleted", laID, userName)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2019 Sorint.lab
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sorintlab/agola/internal/services/gateway/api"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var cmdUserTokenDelete = &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "delete a user token",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := userTokenDelete(cmd, args); err != nil {
|
||||
log.Fatalf("err: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
type userTokenDeleteOptions struct {
|
||||
userName string
|
||||
tokenName string
|
||||
}
|
||||
|
||||
var userTokenDeleteOpts userTokenDeleteOptions
|
||||
|
||||
func init() {
|
||||
flags := cmdUserTokenDelete.Flags()
|
||||
|
||||
flags.StringVarP(&userTokenDeleteOpts.userName, "username", "n", "", "user name")
|
||||
flags.StringVarP(&userTokenDeleteOpts.tokenName, "tokenname", "t", "", "token name")
|
||||
|
||||
cmdUserTokenDelete.MarkFlagRequired("username")
|
||||
cmdUserTokenDelete.MarkFlagRequired("tokenname")
|
||||
|
||||
cmdUserToken.AddCommand(cmdUserTokenDelete)
|
||||
}
|
||||
|
||||
func userTokenDelete(cmd *cobra.Command, args []string) error {
|
||||
gwclient := api.NewClient(gatewayURL, token)
|
||||
|
||||
userName := userTokenDeleteOpts.userName
|
||||
tokenName := userTokenDeleteOpts.tokenName
|
||||
|
||||
log.Infof("deleting token %q for user %q", tokenName, userName)
|
||||
_, err := gwclient.DeleteUserToken(context.TODO(), userName, tokenName)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to delete user token")
|
||||
}
|
||||
|
||||
log.Infof("token %q for user %q deleted", tokenName, userName)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -383,6 +383,10 @@ func (c *Client) CreateUserToken(ctx context.Context, userName string, req *Crea
|
|||
return tresp, resp, err
|
||||
}
|
||||
|
||||
func (c *Client) DeleteUserToken(ctx context.Context, userName, tokenName string) (*http.Response, error) {
|
||||
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/users/%s/tokens/%s", userName, tokenName), nil, jsonContent, nil)
|
||||
}
|
||||
|
||||
func (c *Client) GetRemoteSource(ctx context.Context, rsID string) (*types.RemoteSource, *http.Response, error) {
|
||||
rs := new(types.RemoteSource)
|
||||
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/remotesource/%s", rsID), nil, jsonContent, nil, rs)
|
||||
|
|
|
@ -471,3 +471,24 @@ func (h *CreateUserTokenHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
type DeleteUserTokenHandler struct {
|
||||
log *zap.SugaredLogger
|
||||
ch *command.CommandHandler
|
||||
}
|
||||
|
||||
func NewDeleteUserTokenHandler(logger *zap.Logger, ch *command.CommandHandler) *DeleteUserTokenHandler {
|
||||
return &DeleteUserTokenHandler{log: logger.Sugar(), ch: ch}
|
||||
}
|
||||
|
||||
func (h *DeleteUserTokenHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
userName := vars["username"]
|
||||
tokenName := vars["tokenname"]
|
||||
|
||||
err := h.ch.DeleteUserToken(ctx, userName, tokenName)
|
||||
if httpError(w, err) {
|
||||
h.log.Errorf("err: %+v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -686,6 +686,65 @@ func (s *CommandHandler) CreateUserToken(ctx context.Context, userName, tokenNam
|
|||
return token, err
|
||||
}
|
||||
|
||||
func (s *CommandHandler) DeleteUserToken(ctx context.Context, userName, tokenName string) error {
|
||||
if userName == "" {
|
||||
return util.NewErrBadRequest(errors.Errorf("user name required"))
|
||||
}
|
||||
if tokenName == "" {
|
||||
return util.NewErrBadRequest(errors.Errorf("token name required"))
|
||||
}
|
||||
|
||||
var user *types.User
|
||||
|
||||
var cgt *wal.ChangeGroupsUpdateToken
|
||||
|
||||
// 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, userName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if user == nil {
|
||||
return util.NewErrBadRequest(errors.Errorf("user %q doesn't exist", userName))
|
||||
}
|
||||
|
||||
cgNames := []string{user.ID}
|
||||
cgt, err = s.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, ok := user.Tokens[tokenName]
|
||||
if !ok {
|
||||
return util.NewErrBadRequest(errors.Errorf("token %q for user %q doesn't exist", tokenName, userName))
|
||||
}
|
||||
|
||||
delete(user.Tokens, tokenName)
|
||||
|
||||
userj, err := json.Marshal(user)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to marshal user")
|
||||
}
|
||||
actions := []*wal.Action{
|
||||
{
|
||||
ActionType: wal.ActionTypePut,
|
||||
DataType: string(types.ConfigTypeUser),
|
||||
ID: user.ID,
|
||||
Data: userj,
|
||||
},
|
||||
}
|
||||
|
||||
_, err = s.wal.WriteWal(ctx, actions, cgt)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *CommandHandler) CreateRemoteSource(ctx context.Context, remoteSource *types.RemoteSource) (*types.RemoteSource, error) {
|
||||
if remoteSource.Name == "" {
|
||||
return nil, util.NewErrBadRequest(errors.Errorf("remotesource name required"))
|
||||
|
|
|
@ -144,6 +144,7 @@ func (s *ConfigStore) Run(ctx context.Context) error {
|
|||
updateUserLAHandler := api.NewUpdateUserLAHandler(logger, s.ch)
|
||||
|
||||
createUserTokenHandler := api.NewCreateUserTokenHandler(logger, s.ch)
|
||||
deleteUserTokenHandler := api.NewDeleteUserTokenHandler(logger, s.ch)
|
||||
|
||||
orgHandler := api.NewOrgHandler(logger, s.readDB)
|
||||
orgsHandler := api.NewOrgsHandler(logger, s.readDB)
|
||||
|
@ -193,6 +194,7 @@ func (s *ConfigStore) Run(ctx context.Context) error {
|
|||
apirouter.Handle("/users/{username}/linkedaccounts/{laid}", deleteUserLAHandler).Methods("DELETE")
|
||||
apirouter.Handle("/users/{username}/linkedaccounts/{laid}", updateUserLAHandler).Methods("PUT")
|
||||
apirouter.Handle("/users/{username}/tokens", createUserTokenHandler).Methods("PUT")
|
||||
apirouter.Handle("/users/{username}/tokens/{tokenname}", deleteUserTokenHandler).Methods("DELETE")
|
||||
|
||||
apirouter.Handle("/org/{orgid}", orgHandler).Methods("GET")
|
||||
apirouter.Handle("/orgs", orgsHandler).Methods("GET")
|
||||
|
|
|
@ -306,6 +306,10 @@ func (c *Client) CreateUserToken(ctx context.Context, userName string, req *Crea
|
|||
return tresp, resp, err
|
||||
}
|
||||
|
||||
func (c *Client) DeleteUserToken(ctx context.Context, userName, tokenName string) (*http.Response, error) {
|
||||
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/users/%s/tokens/%s", userName, tokenName), nil, jsonContent, nil)
|
||||
}
|
||||
|
||||
func (c *Client) GetRun(ctx context.Context, runID string) (*RunResponse, *http.Response, error) {
|
||||
run := new(RunResponse)
|
||||
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/run/%s", runID), nil, jsonContent, nil, run)
|
||||
|
|
|
@ -416,6 +416,29 @@ func (h *CreateUserTokenHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|||
}
|
||||
}
|
||||
|
||||
type DeleteUserTokenHandler struct {
|
||||
log *zap.SugaredLogger
|
||||
configstoreClient *csapi.Client
|
||||
}
|
||||
|
||||
func NewDeleteUserTokenHandler(logger *zap.Logger, configstoreClient *csapi.Client) *DeleteUserTokenHandler {
|
||||
return &DeleteUserTokenHandler{log: logger.Sugar(), configstoreClient: configstoreClient}
|
||||
}
|
||||
|
||||
func (h *DeleteUserTokenHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
userName := vars["username"]
|
||||
tokenName := vars["tokenname"]
|
||||
|
||||
h.log.Infof("deleting user %q token %q", userName, tokenName)
|
||||
_, err := h.configstoreClient.DeleteUserToken(ctx, userName, tokenName)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
type RegisterUserRequest struct {
|
||||
CreateUserRequest
|
||||
CreateUserLARequest
|
||||
|
|
|
@ -175,6 +175,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)
|
||||
deleteUserTokenHandler := api.NewDeleteUserTokenHandler(logger, g.configstoreClient)
|
||||
|
||||
remoteSourceHandler := api.NewRemoteSourceHandler(logger, g.configstoreClient)
|
||||
createRemoteSourceHandler := api.NewCreateRemoteSourceHandler(logger, g.configstoreClient)
|
||||
|
@ -247,6 +248,7 @@ func (g *Gateway) Run(ctx context.Context) error {
|
|||
apirouter.Handle("/users/{username}/linkedaccounts", authForcedHandler(createUserLAHandler)).Methods("PUT")
|
||||
apirouter.Handle("/users/{username}/linkedaccounts/{laid}", authForcedHandler(deleteUserLAHandler)).Methods("DELETE")
|
||||
apirouter.Handle("/users/{username}/tokens", authForcedHandler(createUserTokenHandler)).Methods("PUT")
|
||||
apirouter.Handle("/users/{username}/tokens/{tokenname}", authForcedHandler(deleteUserTokenHandler)).Methods("DELETE")
|
||||
|
||||
apirouter.Handle("/remotesource/{id}", authForcedHandler(remoteSourceHandler)).Methods("GET")
|
||||
apirouter.Handle("/remotesources", authForcedHandler(createRemoteSourceHandler)).Methods("PUT")
|
||||
|
|
Loading…
Reference in New Issue