From a4dddc65bab23a59edb6e5d8a4d769294afa8bb8 Mon Sep 17 00:00:00 2001 From: Bogdan Artemenko Date: Wed, 4 Sep 2019 18:02:39 +0300 Subject: [PATCH] web/satellite: Fixed Project Members deletion. (#2891) --- satellite/console/auth.go | 4 +- .../consoleweb/consoleql/consoleerrors.go | 28 +++++ .../consoleql/consoleerrors_test.go | 19 +++ .../console/consoleweb/consoleql/mutation.go | 59 ++++++---- .../console/consoleweb/consoleql/project.go | 22 +++- .../console/consoleweb/consoleql/query.go | 45 +++++-- .../console/consoleweb/consoleql/token.go | 2 +- satellite/console/service.go | 110 ++++++++++-------- .../components/team/ProjectMembersArea.vue | 4 + 9 files changed, 201 insertions(+), 92 deletions(-) create mode 100644 satellite/console/consoleweb/consoleql/consoleerrors.go create mode 100644 satellite/console/consoleweb/consoleql/consoleerrors_test.go diff --git a/satellite/console/auth.go b/satellite/console/auth.go index 6daa4893b..3f2eb67b6 100644 --- a/satellite/console/auth.go +++ b/satellite/console/auth.go @@ -65,8 +65,8 @@ func GetAuth(ctx context.Context) (Authorization, error) { return auth, nil } - if _, ok := value.(error); ok { - return Authorization{}, errs.New(internalErrMsg) + if err, ok := value.(error); ok { + return Authorization{}, err } return Authorization{}, errs.New(unauthorizedErrMsg) diff --git a/satellite/console/consoleweb/consoleql/consoleerrors.go b/satellite/console/consoleweb/consoleql/consoleerrors.go new file mode 100644 index 000000000..5feb0c291 --- /dev/null +++ b/satellite/console/consoleweb/consoleql/consoleerrors.go @@ -0,0 +1,28 @@ +// Copyright (C) 2019 Storj Labs, Inc. +// See LICENSE for copying information. + +package consoleql + +import ( + "github.com/zeebo/errs" + + "storj.io/storj/satellite/console" +) + +// Error messages +const ( + internalErrDetailedMsg = "It looks like we had a problem on our end. Please try again" +) + +// errConsoleInternalDetailed describes detailed error message for internal error +var errConsoleInternalDetailed = errs.New(internalErrDetailedMsg) + +// HandleError returns detailed error if such error handles +func HandleError(err error) error { + switch { + case console.ErrConsoleInternal.Has(err): + return errConsoleInternalDetailed + default: + return err + } +} diff --git a/satellite/console/consoleweb/consoleql/consoleerrors_test.go b/satellite/console/consoleweb/consoleql/consoleerrors_test.go new file mode 100644 index 000000000..acc4975a3 --- /dev/null +++ b/satellite/console/consoleweb/consoleql/consoleerrors_test.go @@ -0,0 +1,19 @@ +// Copyright (C) 2019 Storj Labs, Inc. +// See LICENSE for copying information. + +package consoleql + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "storj.io/storj/satellite/console" +) + +func TestHandleError(t *testing.T) { + err := console.ErrConsoleInternal.New("a") + handledError := HandleError(err) + + assert.Equal(t, handledError.Error(), internalErrDetailedMsg) +} diff --git a/satellite/console/consoleweb/consoleql/mutation.go b/satellite/console/consoleweb/consoleql/mutation.go index 1f82bd048..e008bca3c 100644 --- a/satellite/console/consoleweb/consoleql/mutation.go +++ b/satellite/console/consoleweb/consoleql/mutation.go @@ -102,7 +102,7 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse zap.Error(err)) log.Debug("register: ", zap.String("rawSecret", secretInput)) - return nil, err + return nil, HandleError(err) } token, err := service.GenerateActivationToken(p.Context, user.ID, user.Email) @@ -112,7 +112,7 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse zap.String("email", user.Email), zap.Error(err)) - return user, nil + return user, HandleError(err) } rootObject := p.Info.RootValue.(map[string]interface{}) @@ -147,14 +147,14 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse auth, err := console.GetAuth(p.Context) if err != nil { - return nil, err + return nil, HandleError(err) } info := fillUserInfo(&auth.User, input) err = service.UpdateAccount(p.Context, info) if err != nil { - return nil, err + return nil, HandleError(err) } return auth.User, nil @@ -176,12 +176,12 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse auth, err := console.GetAuth(p.Context) if err != nil { - return nil, err + return nil, HandleError(err) } err = service.ChangePassword(p.Context, pass, newPass) if err != nil { - return nil, err + return nil, HandleError(err) } return auth.User, nil @@ -199,12 +199,12 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse auth, err := console.GetAuth(p.Context) if err != nil { - return nil, err + return nil, HandleError(err) } err = service.DeleteAccount(p.Context, password) if err != nil { - return nil, err + return nil, HandleError(err) } return auth.User, nil @@ -221,7 +221,12 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse Resolve: func(p graphql.ResolveParams) (interface{}, error) { var projectInput = fromMapProjectInfo(p.Args[InputArg].(map[string]interface{})) - return service.CreateProject(p.Context, projectInput) + project, err := service.CreateProject(p.Context, projectInput) + if err != nil { + return nil, HandleError(err) + } + + return project, nil }, }, // deletes project by id, taken from input params @@ -241,11 +246,11 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse project, err := service.GetProject(p.Context, *projectID) if err != nil { - return nil, err + return nil, HandleError(err) } if err = service.DeleteProject(p.Context, project.ID); err != nil { - return nil, err + return nil, HandleError(err) } return project, nil @@ -271,7 +276,12 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse return nil, err } - return service.UpdateProject(p.Context, *projectID, description) + project, err := service.UpdateProject(p.Context, *projectID, description) + if err != nil { + return nil, HandleError(err) + } + + return project, nil }, }, // add user as member of given project @@ -301,12 +311,12 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse project, err := service.GetProject(p.Context, *projectID) if err != nil { - return nil, err + return nil, HandleError(err) } users, err := service.AddProjectMembers(p.Context, *projectID, userEmails) if err != nil { - return nil, err + return nil, HandleError(err) } rootObject := p.Info.RootValue.(map[string]interface{}) @@ -361,10 +371,15 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse err = service.DeleteProjectMembers(p.Context, *projectID, userEmails) if err != nil { - return nil, err + return nil, HandleError(err) } - return service.GetProject(p.Context, *projectID) + project, err := service.GetProject(p.Context, *projectID) + if err != nil { + return nil, HandleError(err) + } + + return project, nil }, }, // creates new api key @@ -389,7 +404,7 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse info, key, err := service.CreateAPIKey(p.Context, *pID, name) if err != nil { - return nil, err + return nil, HandleError(err) } return createAPIKey{ @@ -419,7 +434,7 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse key, err := service.GetAPIKeyInfo(p.Context, *keyID) if err != nil { - return nil, err + return nil, HandleError(err) } keyIds = append(keyIds, *keyID) @@ -428,7 +443,7 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse err := service.DeleteAPIKeys(p.Context, keyIds) if err != nil { - return nil, err + return nil, HandleError(err) } return keys, nil @@ -459,7 +474,7 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse _, err = service.AddNewPaymentMethod(p.Context, cardToken, isDefault, *projID) if err != nil { - return false, err + return false, HandleError(err) } return true, nil @@ -482,7 +497,7 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse err = service.DeleteProjectPaymentMethod(p.Context, *paymentID) if err != nil { - return false, err + return false, HandleError(err) } return true, nil @@ -514,7 +529,7 @@ func rootMutation(log *zap.Logger, service *console.Service, mailService *mailse err = service.SetDefaultPaymentMethod(p.Context, *paymentID, *projectID) if err != nil { - return false, err + return false, HandleError(err) } return true, nil diff --git a/satellite/console/consoleweb/consoleql/project.go b/satellite/console/consoleweb/consoleql/project.go index ff2995b07..3b3c1d58a 100644 --- a/satellite/console/consoleweb/consoleql/project.go +++ b/satellite/console/consoleweb/consoleql/project.go @@ -118,20 +118,20 @@ func graphqlProject(service *console.Service, types *TypeCreator) *graphql.Objec _, err := console.GetAuth(p.Context) if err != nil { - return nil, err + return nil, HandleError(err) } cursor := cursorArgsToProjectMembersCursor(p.Args[CursorArg].(map[string]interface{})) page, err := service.GetProjectMembers(p.Context, project.ID, cursor) if err != nil { - return nil, err + return nil, HandleError(err) } var users []projectMember for _, member := range page.ProjectMembers { user, err := service.GetUser(p.Context, member.MemberID) if err != nil { - return nil, err + return nil, HandleError(err) } users = append(users, projectMember{ @@ -178,7 +178,12 @@ func graphqlProject(service *console.Service, types *TypeCreator) *graphql.Objec since := p.Args[SinceArg].(time.Time) before := p.Args[BeforeArg].(time.Time) - return service.GetProjectUsage(p.Context, project.ID, since, before) + usage, err := service.GetProjectUsage(p.Context, project.ID, since, before) + if err != nil { + return nil, HandleError(err) + } + + return usage, nil }, }, FieldBucketUsages: &graphql.Field{ @@ -197,7 +202,12 @@ func graphqlProject(service *console.Service, types *TypeCreator) *graphql.Objec before := p.Args[BeforeArg].(time.Time) cursor := fromMapBucketUsageCursor(p.Args[CursorArg].(map[string]interface{})) - return service.GetBucketTotals(p.Context, project.ID, cursor, before) + page, err := service.GetBucketTotals(p.Context, project.ID, cursor, before) + if err != nil { + return nil, HandleError(err) + } + + return page, nil }, }, FieldPaymentMethods: &graphql.Field{ @@ -207,7 +217,7 @@ func graphqlProject(service *console.Service, types *TypeCreator) *graphql.Objec paymentMethods, err := service.GetProjectPaymentMethods(p.Context, project.ID) if err != nil { - return nil, err + return nil, HandleError(err) } var projectPaymentMethods []projectPayment diff --git a/satellite/console/consoleweb/consoleql/query.go b/satellite/console/consoleweb/consoleql/query.go index 72916043c..c1713bbd5 100644 --- a/satellite/console/consoleweb/consoleql/query.go +++ b/satellite/console/consoleweb/consoleql/query.go @@ -52,14 +52,19 @@ func rootQuery(service *console.Service, mailService *mailservice.Service, types Resolve: func(p graphql.ResolveParams) (interface{}, error) { id, err := uuidIDAuthFallback(p, FieldID) if err != nil { - return nil, err + return nil, HandleError(err) } _, err = console.GetAuth(p.Context) if err != nil { - return nil, err + return nil, HandleError(err) } - return service.GetUser(p.Context, *id) + user, err := service.GetUser(p.Context, *id) + if err != nil { + return nil, HandleError(err) + } + + return user, nil }, }, ProjectQuery: &graphql.Field{ @@ -77,13 +82,23 @@ func rootQuery(service *console.Service, mailService *mailservice.Service, types return nil, err } - return service.GetProject(p.Context, *id) + project, err := service.GetProject(p.Context, *id) + if err != nil { + return nil, HandleError(err) + } + + return project, nil }, }, MyProjectsQuery: &graphql.Field{ Type: graphql.NewList(types.project), Resolve: func(p graphql.ResolveParams) (interface{}, error) { - return service.GetUsersProjects(p.Context) + projects, err := service.GetUsersProjects(p.Context) + if err != nil { + return nil, HandleError(err) + } + + return projects, nil }, }, ActiveRewardQuery: &graphql.Field{ @@ -96,13 +111,23 @@ func rootQuery(service *console.Service, mailService *mailservice.Service, types Resolve: func(p graphql.ResolveParams) (interface{}, error) { rewardType, _ := p.Args[FieldType].(int) - return service.GetCurrentRewardByType(p.Context, rewards.OfferType(rewardType)) + offer, err := service.GetCurrentRewardByType(p.Context, rewards.OfferType(rewardType)) + if err != nil { + return nil, HandleError(err) + } + + return offer, nil }, }, CreditUsageQuery: &graphql.Field{ Type: types.creditUsage, Resolve: func(p graphql.ResolveParams) (interface{}, error) { - return service.GetUserCreditUsage(p.Context) + usage, err := service.GetUserCreditUsage(p.Context) + if err != nil { + return nil, HandleError(err) + } + + return usage, nil }, }, TokenQuery: &graphql.Field{ @@ -121,7 +146,7 @@ func rootQuery(service *console.Service, mailService *mailservice.Service, types token, err := service.Token(p.Context, email, pass) if err != nil { - return nil, err + return nil, HandleError(err) } return tokenWrapper{Token: token}, nil @@ -187,12 +212,12 @@ func rootQuery(service *console.Service, mailService *mailservice.Service, types user, err := service.GetUser(p.Context, *userID) if err != nil { - return false, err + return false, HandleError(err) } token, err := service.GenerateActivationToken(p.Context, user.ID, user.Email) if err != nil { - return false, err + return false, HandleError(err) } rootObject := p.Info.RootValue.(map[string]interface{}) diff --git a/satellite/console/consoleweb/consoleql/token.go b/satellite/console/consoleweb/consoleql/token.go index 02862d421..24418339a 100644 --- a/satellite/console/consoleweb/consoleql/token.go +++ b/satellite/console/consoleweb/consoleql/token.go @@ -32,7 +32,7 @@ func graphqlToken(service *console.Service, types *TypeCreator) *graphql.Object auth, err := service.Authorize(ctx) if err != nil { - return nil, err + return nil, HandleError(err) } // pass context to root value so child resolvers could get auth auth diff --git a/satellite/console/service.go b/satellite/console/service.go index c29832a3a..da71f0552 100644 --- a/satellite/console/service.go +++ b/satellite/console/service.go @@ -38,7 +38,6 @@ const ( // Error messages const ( - internalErrMsg = "It looks like we had a problem on our end. Please try again" unauthorizedErrMsg = "You are not authorized to perform this action" vanguardRegTokenErrMsg = "We are unable to create your account. This is an invite-only alpha, please join our waitlist to receive an invitation" emailUsedErrMsg = "This email is already in use, try another" @@ -47,6 +46,7 @@ const ( credentialsErrMsg = "Your email or password was incorrect, please try again" oldPassIncorrectErrMsg = "Old password is incorrect, please try again" passwordIncorrectErrMsg = "Your password needs at least %d characters long" + projectOwnerDeletionForbiddenErrMsg = "%s is a project owner and can not be deleted" teamMemberDoesNotExistErrMsg = `There is no account on this Satellite for the user(s) you have entered. Please add team members with active accounts` @@ -55,6 +55,9 @@ const ( projLimitVanguardErrMsg = "Sorry, during the Vanguard release you have a limited number of projects" ) +// ErrConsoleInternal describes internal console error +var ErrConsoleInternal = errs.Class("internal error") + // Service is handling accounts related logic type Service struct { Signer @@ -110,12 +113,12 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R offers, err := s.rewards.GetActiveOffersByType(ctx, offerType) if err != nil && !rewards.NoCurrentOfferErr.Has(err) { s.log.Error("internal error", zap.Error(err)) - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } currentReward, err := offers.GetActiveOffer(offerType, user.PartnerID) if err != nil && !rewards.NoCurrentOfferErr.Has(err) { s.log.Error("internal error", zap.Error(err)) - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } // TODO: remove after vanguard release @@ -126,7 +129,7 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R // set the project limit to be 1 for open source partner invitees registrationToken, err = s.store.RegistrationTokens().Create(ctx, 1) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } } else { registrationToken, err = s.store.RegistrationTokens().GetBySecret(ctx, tokenSecret) @@ -151,7 +154,7 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), s.passwordCost) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } // store data @@ -170,7 +173,7 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R if user.PartnerID != "" { partnerID, err := uuid.Parse(user.PartnerID) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } newUser.PartnerID = *partnerID } @@ -179,12 +182,12 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R newUser, ) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } err = tx.RegistrationTokens().UpdateOwner(ctx, registrationToken.Secret, u.ID) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } if currentReward != nil { @@ -192,7 +195,7 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser, tokenSecret R if refUserID != "" { refID, err = uuid.Parse(refUserID) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } } newCredit, err := NewCredit(currentReward, Invitee, u.ID, refID) @@ -425,7 +428,7 @@ func (s *Service) ActivateAccount(ctx context.Context, activationToken string) ( token, err := consoleauth.FromBase64URLString(activationToken) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } claims, err := s.authenticate(ctx, token) @@ -440,7 +443,7 @@ func (s *Service) ActivateAccount(ctx context.Context, activationToken string) ( user, err := s.store.Users().Get(ctx, claims.ID) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } now := time.Now() @@ -456,12 +459,12 @@ func (s *Service) ActivateAccount(ctx context.Context, activationToken string) ( user.Status = Active err = s.store.Users().Update(ctx, user) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } err = s.store.UserCredits().UpdateEarnedCredits(ctx, user.ID) if err != nil && !NoCreditForUpdateErr.Has(err) { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } return nil @@ -555,7 +558,7 @@ func (s *Service) GetUser(ctx context.Context, id uuid.UUID) (u *User, err error user, err := s.store.Users().Get(ctx, id) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } return user, nil @@ -589,7 +592,7 @@ func (s *Service) UpdateAccount(ctx context.Context, info UserInfo) (err error) Status: auth.User.Status, }) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } return nil @@ -614,13 +617,13 @@ func (s *Service) ChangePassword(ctx context.Context, pass, newPass string) (err hash, err := bcrypt.GenerateFromPassword([]byte(newPass), s.passwordCost) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } auth.User.PasswordHash = hash err = s.store.Users().Update(ctx, &auth.User) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } return nil @@ -641,7 +644,7 @@ func (s *Service) DeleteAccount(ctx context.Context, password string) (err error err = s.store.Users().Delete(ctx, auth.User.ID) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } return nil @@ -657,7 +660,7 @@ func (s *Service) GetProject(ctx context.Context, projectID uuid.UUID) (p *Proje p, err = s.store.Projects().Get(ctx, projectID) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } return @@ -673,7 +676,7 @@ func (s *Service) GetUsersProjects(ctx context.Context) (ps []Project, err error ps, err = s.store.Projects().GetByUserID(ctx, auth.User.ID) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } return @@ -686,7 +689,7 @@ func (s *Service) GetCurrentRewardByType(ctx context.Context, offerType rewards. offers, err := s.rewards.GetActiveOffersByType(ctx, offerType) if err != nil { s.log.Error("internal error", zap.Error(err)) - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } return offers.GetActiveOffer(offerType, "") } @@ -723,7 +726,7 @@ func (s *Service) CreateProject(ctx context.Context, projectInfo ProjectInfo) (p tx, err := s.store.BeginTx(ctx) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } err = withTx(tx, func(tx DBTx) (err error) { @@ -737,12 +740,12 @@ func (s *Service) CreateProject(ctx context.Context, projectInfo ProjectInfo) (p ) if err != nil { s.log.Error("internal error", zap.Error(err)) - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } _, err = tx.ProjectMembers().Insert(ctx, auth.User.ID, p.ID) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } return err @@ -769,7 +772,7 @@ func (s *Service) DeleteProject(ctx context.Context, projectID uuid.UUID) (err e err = s.store.Projects().Delete(ctx, projectID) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } return nil @@ -793,7 +796,7 @@ func (s *Service) UpdateProject(ctx context.Context, projectID uuid.UUID, descri err = s.store.Projects().Update(ctx, project) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } return project, nil @@ -831,7 +834,7 @@ func (s *Service) AddProjectMembers(ctx context.Context, projectID uuid.UUID, em // add project members in transaction scope tx, err := s.store.BeginTx(ctx) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } defer func() { @@ -847,7 +850,7 @@ func (s *Service) AddProjectMembers(ctx context.Context, projectID uuid.UUID, em _, err = tx.ProjectMembers().Insert(ctx, user.ID, projectID) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } } @@ -857,15 +860,11 @@ func (s *Service) AddProjectMembers(ctx context.Context, projectID uuid.UUID, em // DeleteProjectMembers removes users by email from given project func (s *Service) DeleteProjectMembers(ctx context.Context, projectID uuid.UUID, emails []string) (err error) { defer mon.Task()(&ctx)(&err) - auth, err := GetAuth(ctx) + _, err = GetAuth(ctx) if err != nil { return err } - if err = s.isProjectOwner(ctx, auth.User.ID, projectID); err != nil { - return err - } - var userIDs []uuid.UUID var userErr errs.Group @@ -878,6 +877,15 @@ func (s *Service) DeleteProjectMembers(ctx context.Context, projectID uuid.UUID, continue } + err = s.isProjectOwner(ctx, user.ID, projectID) + if err == nil { + return errs.New(projectOwnerDeletionForbiddenErrMsg, user.Email) + } + + if ErrConsoleInternal.Has(err) { + return err + } + userIDs = append(userIDs, user.ID) } @@ -904,7 +912,7 @@ func (s *Service) DeleteProjectMembers(ctx context.Context, projectID uuid.UUID, err = tx.ProjectMembers().Delete(ctx, uID, projectID) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } } @@ -930,7 +938,7 @@ func (s *Service) GetProjectMembers(ctx context.Context, projectID uuid.UUID, cu pmp, err = s.store.ProjectMembers().GetPagedByProjectID(ctx, projectID, cursor) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } return @@ -952,7 +960,7 @@ func (s *Service) CreateAPIKey(ctx context.Context, projectID uuid.UUID, name st secret, err := macaroon.NewSecret() if err != nil { - return nil, nil, errs.New(internalErrMsg) + return nil, nil, ErrConsoleInternal.Wrap(err) } key, err := macaroon.NewAPIKey(secret) @@ -969,7 +977,7 @@ func (s *Service) CreateAPIKey(ctx context.Context, projectID uuid.UUID, name st info, err := s.store.APIKeys().Create(ctx, key.Head(), apikey) if err != nil { - return nil, nil, errs.New(internalErrMsg) + return nil, nil, ErrConsoleInternal.Wrap(err) } return info, key, nil @@ -986,7 +994,7 @@ func (s *Service) GetAPIKeyInfo(ctx context.Context, id uuid.UUID) (_ *APIKeyInf key, err := s.store.APIKeys().Get(ctx, id) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } _, err = s.isProjectMember(ctx, auth.User.ID, key.ProjectID) @@ -1022,12 +1030,12 @@ func (s *Service) DeleteAPIKeys(ctx context.Context, ids []uuid.UUID) (err error } if err = keysErr.Err(); err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } tx, err := s.store.BeginTx(ctx) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } defer func() { @@ -1042,7 +1050,7 @@ func (s *Service) DeleteAPIKeys(ctx context.Context, ids []uuid.UUID) (err error for _, keyToDeleteID := range ids { err = tx.APIKeys().Delete(ctx, keyToDeleteID) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } } @@ -1064,7 +1072,7 @@ func (s *Service) GetAPIKeysInfoByProjectID(ctx context.Context, projectID uuid. info, err = s.store.APIKeys().GetByProjectID(ctx, projectID) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } return info, nil @@ -1086,7 +1094,7 @@ func (s *Service) GetProjectUsage(ctx context.Context, projectID uuid.UUID, sinc projectUsage, err := s.store.UsageRollups().GetProjectTotal(ctx, projectID, since, before) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } return projectUsage, nil @@ -1247,7 +1255,7 @@ func (s *Service) checkProjectLimit(ctx context.Context, userID uuid.UUID) (err projects, err := s.GetUsersProjects(ctx) if err != nil { - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } if len(projects) >= registrationToken.ProjectLimit { return errs.New(projLimitVanguardErrMsg) @@ -1268,13 +1276,13 @@ func (s *Service) createToken(ctx context.Context, claims *consoleauth.Claims) ( json, err := claims.JSON() if err != nil { - return "", errs.New(internalErrMsg) + return "", ErrConsoleInternal.Wrap(err) } token := consoleauth.Token{Payload: json} err = signToken(&token, s.Signer) if err != nil { - return "", errs.New(internalErrMsg) + return "", ErrConsoleInternal.Wrap(err) } return token.String(), nil @@ -1287,7 +1295,7 @@ func (s *Service) authenticate(ctx context.Context, token consoleauth.Token) (_ err = signToken(&token, s.Signer) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } if subtle.ConstantTimeCompare(signature, token.Signature) != 1 { @@ -1296,7 +1304,7 @@ func (s *Service) authenticate(ctx context.Context, token consoleauth.Token) (_ claims, err := consoleauth.FromJSON(token.Payload) if err != nil { - return nil, errs.New(internalErrMsg) + return nil, ErrConsoleInternal.Wrap(err) } return claims, nil @@ -1332,7 +1340,7 @@ func (s *Service) isProjectOwner(ctx context.Context, userID uuid.UUID, projectI project, err := s.store.Projects().Get(ctx, projectID) if err != nil { s.log.Error("internal error", zap.Error(err)) - return errs.New(internalErrMsg) + return ErrConsoleInternal.Wrap(err) } if project.OwnerID != userID { @@ -1347,12 +1355,12 @@ func (s *Service) isProjectMember(ctx context.Context, userID uuid.UUID, project defer mon.Task()(&ctx)(&err) project, err := s.store.Projects().Get(ctx, projectID) if err != nil { - return result, errs.New(internalErrMsg) + return result, ErrConsoleInternal.Wrap(err) } memberships, err := s.store.ProjectMembers().GetByMemberID(ctx, userID) if err != nil { - return result, errs.New(internalErrMsg) + return result, ErrConsoleInternal.Wrap(err) } for _, membership := range memberships { diff --git a/web/satellite/src/components/team/ProjectMembersArea.vue b/web/satellite/src/components/team/ProjectMembersArea.vue index 3a95284ba..0db193d6e 100644 --- a/web/satellite/src/components/team/ProjectMembersArea.vue +++ b/web/satellite/src/components/team/ProjectMembersArea.vue @@ -79,6 +79,10 @@ export default class ProjectMembersArea extends Vue { private FIRST_PAGE = 1; + public async beforeDestroy(): Promise { + await this.$store.dispatch(PM_ACTIONS.CLEAR_SELECTION); + } + public onMemberClick(member: ProjectMember): void { this.$store.dispatch(PM_ACTIONS.TOGGLE_SELECTION, member.user.id); }