Implement user token delete
This commit is contained in:
parent
3a41e66f5b
commit
c4310be7de
|
@ -17,9 +17,9 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/sorintlab/agola/internal/services/gateway/api"
|
"github.com/sorintlab/agola/internal/services/gateway/api"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -58,13 +58,13 @@ func userLADelete(cmd *cobra.Command, args []string) error {
|
||||||
userName := userLADeleteOpts.userName
|
userName := userLADeleteOpts.userName
|
||||||
laID := userLADeleteOpts.laID
|
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)
|
_, err := gwclient.DeleteUserLA(context.TODO(), userName, laID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to delete linked account")
|
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
|
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
|
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) {
|
func (c *Client) GetRemoteSource(ctx context.Context, rsID string) (*types.RemoteSource, *http.Response, error) {
|
||||||
rs := new(types.RemoteSource)
|
rs := new(types.RemoteSource)
|
||||||
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/remotesource/%s", rsID), nil, jsonContent, nil, rs)
|
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
|
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
|
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) {
|
func (s *CommandHandler) CreateRemoteSource(ctx context.Context, remoteSource *types.RemoteSource) (*types.RemoteSource, error) {
|
||||||
if remoteSource.Name == "" {
|
if remoteSource.Name == "" {
|
||||||
return nil, util.NewErrBadRequest(errors.Errorf("remotesource name required"))
|
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)
|
updateUserLAHandler := api.NewUpdateUserLAHandler(logger, s.ch)
|
||||||
|
|
||||||
createUserTokenHandler := api.NewCreateUserTokenHandler(logger, s.ch)
|
createUserTokenHandler := api.NewCreateUserTokenHandler(logger, s.ch)
|
||||||
|
deleteUserTokenHandler := api.NewDeleteUserTokenHandler(logger, s.ch)
|
||||||
|
|
||||||
orgHandler := api.NewOrgHandler(logger, s.readDB)
|
orgHandler := api.NewOrgHandler(logger, s.readDB)
|
||||||
orgsHandler := api.NewOrgsHandler(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}", deleteUserLAHandler).Methods("DELETE")
|
||||||
apirouter.Handle("/users/{username}/linkedaccounts/{laid}", updateUserLAHandler).Methods("PUT")
|
apirouter.Handle("/users/{username}/linkedaccounts/{laid}", updateUserLAHandler).Methods("PUT")
|
||||||
apirouter.Handle("/users/{username}/tokens", createUserTokenHandler).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("/org/{orgid}", orgHandler).Methods("GET")
|
||||||
apirouter.Handle("/orgs", orgsHandler).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
|
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) {
|
func (c *Client) GetRun(ctx context.Context, runID string) (*RunResponse, *http.Response, error) {
|
||||||
run := new(RunResponse)
|
run := new(RunResponse)
|
||||||
resp, err := c.getParsedResponse(ctx, "GET", fmt.Sprintf("/run/%s", runID), nil, jsonContent, nil, run)
|
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 {
|
type RegisterUserRequest struct {
|
||||||
CreateUserRequest
|
CreateUserRequest
|
||||||
CreateUserLARequest
|
CreateUserLARequest
|
||||||
|
|
|
@ -175,6 +175,7 @@ func (g *Gateway) Run(ctx context.Context) error {
|
||||||
createUserLAHandler := api.NewCreateUserLAHandler(logger, g.ch)
|
createUserLAHandler := api.NewCreateUserLAHandler(logger, g.ch)
|
||||||
deleteUserLAHandler := api.NewDeleteUserLAHandler(logger, g.configstoreClient)
|
deleteUserLAHandler := api.NewDeleteUserLAHandler(logger, g.configstoreClient)
|
||||||
createUserTokenHandler := api.NewCreateUserTokenHandler(logger, g.configstoreClient)
|
createUserTokenHandler := api.NewCreateUserTokenHandler(logger, g.configstoreClient)
|
||||||
|
deleteUserTokenHandler := api.NewDeleteUserTokenHandler(logger, g.configstoreClient)
|
||||||
|
|
||||||
remoteSourceHandler := api.NewRemoteSourceHandler(logger, g.configstoreClient)
|
remoteSourceHandler := api.NewRemoteSourceHandler(logger, g.configstoreClient)
|
||||||
createRemoteSourceHandler := api.NewCreateRemoteSourceHandler(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", authForcedHandler(createUserLAHandler)).Methods("PUT")
|
||||||
apirouter.Handle("/users/{username}/linkedaccounts/{laid}", authForcedHandler(deleteUserLAHandler)).Methods("DELETE")
|
apirouter.Handle("/users/{username}/linkedaccounts/{laid}", authForcedHandler(deleteUserLAHandler)).Methods("DELETE")
|
||||||
apirouter.Handle("/users/{username}/tokens", authForcedHandler(createUserTokenHandler)).Methods("PUT")
|
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("/remotesource/{id}", authForcedHandler(remoteSourceHandler)).Methods("GET")
|
||||||
apirouter.Handle("/remotesources", authForcedHandler(createRemoteSourceHandler)).Methods("PUT")
|
apirouter.Handle("/remotesources", authForcedHandler(createRemoteSourceHandler)).Methods("PUT")
|
||||||
|
|
Loading…
Reference in New Issue