From e287364b785ac191ed8949059386077ad725afd5 Mon Sep 17 00:00:00 2001 From: kolaente Date: Thu, 20 Mar 2025 17:13:51 +0100 Subject: [PATCH] fix(team): do not allow leaving exernal teams --- frontend/src/modelTypes/ITeam.ts | 2 +- frontend/src/models/team.ts | 2 +- frontend/src/views/teams/EditTeam.vue | 2 +- pkg/models/error.go | 20 ++++++++++++++++++++ pkg/models/team_members.go | 10 ++++++++++ 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/frontend/src/modelTypes/ITeam.ts b/frontend/src/modelTypes/ITeam.ts index e9e7142cb..7f9a578fe 100644 --- a/frontend/src/modelTypes/ITeam.ts +++ b/frontend/src/modelTypes/ITeam.ts @@ -9,7 +9,7 @@ export interface ITeam extends IAbstract { description: string members: ITeamMember[] right: Right - oidcId: string + externalId: string isPublic: boolean createdBy: IUser diff --git a/frontend/src/models/team.ts b/frontend/src/models/team.ts index cc17849fa..6715e20ec 100644 --- a/frontend/src/models/team.ts +++ b/frontend/src/models/team.ts @@ -13,7 +13,7 @@ export default class TeamModel extends AbstractModel implements ITeam { description = '' members: ITeamMember[] = [] right: Right = RIGHTS.READ - oidcId = '' + externalId = '' isPublic: boolean = false createdBy: IUser = {} // FIXME: seems wrong diff --git a/frontend/src/views/teams/EditTeam.vue b/frontend/src/views/teams/EditTeam.vue index 1dc5696d9..a7e67b1ef 100644 --- a/frontend/src/views/teams/EditTeam.vue +++ b/frontend/src/views/teams/EditTeam.vue @@ -194,7 +194,7 @@ diff --git a/pkg/models/error.go b/pkg/models/error.go index 7852dd13b..59bec8242 100644 --- a/pkg/models/error.go +++ b/pkg/models/error.go @@ -1366,6 +1366,26 @@ func (err ErrOIDCTeamsDoNotExistForUser) HTTPError() web.HTTPError { } } +// ErrCannotRemoveUserFromExternalTeam represents an error where an oidcTeam does not exist for the user +type ErrCannotRemoveUserFromExternalTeam struct { + TeamID int64 +} + +func (err ErrCannotRemoveUserFromExternalTeam) Error() string { + return fmt.Sprintf("Users cannot be removed from an external team [Team ID: %d]", err.TeamID) +} + +const ErrCodeCannotLeaveExternalTeam = 6010 + +// HTTPError holds the http error description +func (err ErrCannotRemoveUserFromExternalTeam) HTTPError() web.HTTPError { + return web.HTTPError{ + HTTPCode: http.StatusPreconditionFailed, + Code: ErrCodeCannotLeaveExternalTeam, + Message: "Users cannot be removed from an external team.", + } +} + // ==================== // User <-> Project errors // ==================== diff --git a/pkg/models/team_members.go b/pkg/models/team_members.go index 0c37bf240..4b6d2d67f 100644 --- a/pkg/models/team_members.go +++ b/pkg/models/team_members.go @@ -20,6 +20,7 @@ import ( "code.vikunja.io/api/pkg/events" user2 "code.vikunja.io/api/pkg/user" "code.vikunja.io/api/pkg/web" + "xorm.io/xorm" ) @@ -89,6 +90,15 @@ func (tm *TeamMember) Create(s *xorm.Session, a web.Auth) (err error) { // @Router /teams/{id}/members/{username} [delete] func (tm *TeamMember) Delete(s *xorm.Session, _ web.Auth) (err error) { + t, err := GetTeamByID(s, tm.TeamID) + if err != nil { + return err + } + + if t.ExternalID != "" { + return ErrCannotRemoveUserFromExternalTeam{tm.TeamID} + } + total, err := s.Where("team_id = ?", tm.TeamID).Count(&TeamMember{}) if err != nil { return