diff --git a/api/cache/group_cache.go b/api/cache/group_cache.go index b4d9cb66a..bf0b92f34 100644 --- a/api/cache/group_cache.go +++ b/api/cache/group_cache.go @@ -66,3 +66,10 @@ func (c *GroupCache) Refresh(id string) (model.Group, error) { } return res, nil } + +func (c *GroupCache) Delete(id string) error { + if err := c.redis.Delete(c.keyPrefix + id); err != nil { + return err + } + return nil +} diff --git a/api/errorpkg/error_creators.go b/api/errorpkg/error_creators.go index 44b2f4812..496acb7b1 100644 --- a/api/errorpkg/error_creators.go +++ b/api/errorpkg/error_creators.go @@ -243,11 +243,22 @@ func NewOrganizationPermissionError(userID string, org model.Organization, permi ) } -func NewCannotRemoveLastRemainingOwnerOfOrganizationError(id string) *ErrorResponse { +func NewCannotRemoveLastRemainingOwnerOfOrganizationError(org model.Organization) *ErrorResponse { return NewErrorResponse( "cannot_remove_last_owner_of_organization", http.StatusBadRequest, - fmt.Sprintf("Cannot remove the last remaining owner of organization '%s'.", id), MsgInvalidRequest, + fmt.Sprintf("Cannot remove the last remaining owner of organization '%s'.", org.GetID()), + fmt.Sprintf("Cannot remove the last remaining owner of organization '%s'.", org.GetName()), + nil, + ) +} + +func NewCannotRemoveLastRemainingOwnerOfGroupError(group model.Group) *ErrorResponse { + return NewErrorResponse( + "cannot_remove_last_owner_of_group", + http.StatusBadRequest, + fmt.Sprintf("Cannot remove the last remaining owner of group '%s'.", group.GetID()), + fmt.Sprintf("Cannot remove the last remaining owner of group '%s'.", group.GetName()), nil, ) } diff --git a/api/repo/group_repo.go b/api/repo/group_repo.go index b964cf097..3fa3081cf 100644 --- a/api/repo/group_repo.go +++ b/api/repo/group_repo.go @@ -25,15 +25,13 @@ type GroupRepo interface { Insert(opts GroupInsertOptions) (model.Group, error) Find(id string) (model.Group, error) Count() (int64, error) - GetIDsForFile(fileID string) ([]string, error) - GetIDsForUser(userID string) ([]string, error) - GetIDsForOrganization(id string) ([]string, error) + GetIDs() ([]string, error) + GetIDsByFile(fileID string) ([]string, error) + GetIDsByOrganization(id string) ([]string, error) Save(group model.Group) error Delete(id string) error - AddUser(id string, userID string) error - RemoveMember(id string, userID string) error - GetIDs() ([]string, error) GetMembers(id string) ([]model.User, error) + GetOwnerCount(id string) (int64, error) GrantUserPermission(id string, userID string, permission string) error RevokeUserPermission(id string, userID string) error } @@ -193,7 +191,7 @@ func (repo *groupRepo) Count() (int64, error) { return res.Result, nil } -func (repo *groupRepo) GetIDsForFile(fileID string) ([]string, error) { +func (repo *groupRepo) GetIDsByFile(fileID string) ([]string, error) { type Value struct { Result string } @@ -214,23 +212,7 @@ func (repo *groupRepo) GetIDsForFile(fileID string) ([]string, error) { return res, nil } -func (repo *groupRepo) GetIDsForUser(userID string) ([]string, error) { - type Value struct { - Result string - } - var values []Value - db := repo.db.Raw(`SELECT group_id from group_user WHERE user_id = ?`, userID).Scan(&values) - if db.Error != nil { - return []string{}, db.Error - } - res := []string{} - for _, v := range values { - res = append(res, v.Result) - } - return res, nil -} - -func (repo *groupRepo) GetIDsForOrganization(id string) ([]string, error) { +func (repo *groupRepo) GetIDsByOrganization(id string) ([]string, error) { type Value struct { Result string } @@ -270,22 +252,6 @@ func (repo *groupRepo) Delete(id string) error { return nil } -func (repo *groupRepo) AddUser(id string, userID string) error { - db := repo.db.Exec("INSERT INTO group_user (group_id, user_id, create_time) VALUES (?, ?, ?)", id, userID, helper.NewTimestamp()) - if db.Error != nil { - return db.Error - } - return nil -} - -func (repo *groupRepo) RemoveMember(id string, userID string) error { - db := repo.db.Exec("DELETE FROM group_user WHERE group_id = ? AND user_id = ?", id, userID) - if db.Error != nil { - return db.Error - } - return nil -} - func (repo *groupRepo) GetIDs() ([]string, error) { type Value struct { Result string @@ -305,7 +271,8 @@ func (repo *groupRepo) GetIDs() ([]string, error) { func (repo *groupRepo) GetMembers(id string) ([]model.User, error) { var entities []*userEntity db := repo.db. - Raw(`SELECT DISTINCT u.* FROM "user" u INNER JOIN group_user gu ON u.id = gu.user_id WHERE gu.group_id = ?`, id). + Raw(`SELECT u.* FROM "user" u INNER JOIN userpermission up on + u.id = up.user_id AND up.resource_id = ?`, id). Scan(&entities) if db.Error != nil { return nil, db.Error @@ -317,6 +284,22 @@ func (repo *groupRepo) GetMembers(id string) ([]model.User, error) { return res, nil } +func (repo *groupRepo) GetOwnerCount(id string) (int64, error) { + type Result struct { + Result int64 + } + var res Result + db := repo.db. + Raw(`SELECT count(*) as result FROM userpermission + WHERE resource_id = ? and permission = ?`, + id, model.PermissionOwner). + Scan(&res) + if db.Error != nil { + return 0, db.Error + } + return res.Result, nil +} + func (repo *groupRepo) GrantUserPermission(id string, userID string, permission string) error { db := repo.db. Exec(`INSERT INTO userpermission (id, user_id, resource_id, permission, create_time) diff --git a/api/repo/organization_repo.go b/api/repo/organization_repo.go index a13b95043..efa56c116 100644 --- a/api/repo/organization_repo.go +++ b/api/repo/organization_repo.go @@ -28,8 +28,6 @@ type OrganizationRepo interface { Save(org model.Organization) error Delete(id string) error GetIDs() ([]string, error) - AddUser(id string, userID string) error - RemoveMember(id string, userID string) error GetMembers(id string) ([]model.User, error) GetGroups(id string) ([]model.Group, error) GetOwnerCount(id string) (int64, error) @@ -222,28 +220,11 @@ func (repo *organizationRepo) GetIDs() ([]string, error) { return res, nil } -func (repo *organizationRepo) AddUser(id string, userID string) error { - db := repo.db.Exec("INSERT INTO organization_user (organization_id, user_id, create_time) VALUES (?, ?, ?)", id, userID, helper.NewTimestamp()) - if db.Error != nil { - return db.Error - } - return nil -} - -func (repo *organizationRepo) RemoveMember(id string, userID string) error { - db := repo.db.Exec("DELETE FROM organization_user WHERE organization_id = ? AND user_id = ?", id, userID) - if db.Error != nil { - return db.Error - } - return nil -} - func (repo *organizationRepo) GetMembers(id string) ([]model.User, error) { var entities []*userEntity db := repo.db. - Raw(`SELECT DISTINCT u.* FROM "user" u - INNER JOIN organization_user ou ON u.id = ou.user_id - WHERE ou.organization_id = ? ORDER BY u.full_name`, + Raw(`SELECT u.* FROM "user" u INNER JOIN userpermission up on + u.id = up.user_id AND up.resource_id = ?`, id). Scan(&entities) if db.Error != nil { diff --git a/api/repo/snapshot_repo.go b/api/repo/snapshot_repo.go index ae99e17c6..3ed6eb6bb 100644 --- a/api/repo/snapshot_repo.go +++ b/api/repo/snapshot_repo.go @@ -30,7 +30,7 @@ type SnapshotRepo interface { FindAllForFile(fileID string) ([]model.Snapshot, error) FindAllDangling() ([]model.Snapshot, error) FindAllPrevious(fileID string, version int64) ([]model.Snapshot, error) - GetIDsForFile(fileID string) ([]string, error) + GetIDsByFile(fileID string) ([]string, error) Insert(snapshot model.Snapshot) error Save(snapshot model.Snapshot) error Delete(id string) error @@ -561,7 +561,7 @@ func (repo *snapshotRepo) FindAllPrevious(fileID string, version int64) ([]model return res, nil } -func (repo *snapshotRepo) GetIDsForFile(fileID string) ([]string, error) { +func (repo *snapshotRepo) GetIDsByFile(fileID string) ([]string, error) { type Value struct { Result string } diff --git a/api/repo/task_repo.go b/api/repo/task_repo.go index f6ebf33a0..3d88ed681 100644 --- a/api/repo/task_repo.go +++ b/api/repo/task_repo.go @@ -148,7 +148,7 @@ type TaskRepo interface { Find(id string) (model.Task, error) Count() (int64, error) GetIDs(userID string) ([]string, error) - GetCount(email string) (int64, error) + GetCountByEmail(email string) (int64, error) Save(task model.Task) error Delete(id string) error } @@ -258,7 +258,7 @@ func (repo *taskRepo) GetIDs(userID string) ([]string, error) { return res, nil } -func (repo *taskRepo) GetCount(userID string) (int64, error) { +func (repo *taskRepo) GetCountByEmail(userID string) (int64, error) { var count int64 db := repo.db. Model(&taskEntity{}). diff --git a/api/repo/workspace_repo.go b/api/repo/workspace_repo.go index 4286e5965..ffadd7169 100644 --- a/api/repo/workspace_repo.go +++ b/api/repo/workspace_repo.go @@ -32,6 +32,7 @@ type WorkspaceRepo interface { GetIDs() ([]string, error) GetIDsByOrganization(orgID string) ([]string, error) GrantUserPermission(id string, userID string, permission string) error + RevokeUserPermission(id string, userID string) error } func NewWorkspaceRepo() WorkspaceRepo { @@ -313,6 +314,14 @@ func (repo *workspaceRepo) GrantUserPermission(id string, userID string, permiss return nil } +func (repo *workspaceRepo) RevokeUserPermission(id string, userID string) error { + db := repo.db.Exec("DELETE FROM userpermission WHERE user_id = ? AND resource_id = ?", userID, id) + if db.Error != nil { + return db.Error + } + return nil +} + func (repo *workspaceRepo) populateModelFields(workspaces []*workspaceEntity) error { for _, w := range workspaces { w.UserPermissions = make([]*UserPermissionValue, 0) diff --git a/api/router/user_router.go b/api/router/user_router.go index 4bb9737b3..5117d2499 100644 --- a/api/router/user_router.go +++ b/api/router/user_router.go @@ -81,9 +81,9 @@ func (r *UserRouter) List(c *fiber.Ctx) error { return errorpkg.NewInvalidQueryParamError("sort_order") } userID := GetUserID(c) - var nonGroupMembersOnly bool - if c.Query("non_group_members_only") != "" { - nonGroupMembersOnly, err = strconv.ParseBool(c.Query("non_group_members_only")) + var excludeGroupMembers bool + if c.Query("exclude_group_members") != "" { + excludeGroupMembers, err = strconv.ParseBool(c.Query("exclude_group_members")) if err != nil { return err } @@ -96,7 +96,7 @@ func (r *UserRouter) List(c *fiber.Ctx) error { Query: query, OrganizationID: c.Query("organization_id"), GroupID: c.Query("group_id"), - NonGroupMembersOnly: nonGroupMembersOnly, + ExcludeGroupMembers: excludeGroupMembers, SortBy: sortBy, SortOrder: sortOrder, Page: uint(page), diff --git a/api/service/group_service.go b/api/service/group_service.go index 5f2f34120..33d7d3b08 100644 --- a/api/service/group_service.go +++ b/api/service/group_service.go @@ -16,6 +16,7 @@ import ( "github.com/kouprlabs/voltaserve/api/cache" "github.com/kouprlabs/voltaserve/api/config" + "github.com/kouprlabs/voltaserve/api/errorpkg" "github.com/kouprlabs/voltaserve/api/guard" "github.com/kouprlabs/voltaserve/api/helper" "github.com/kouprlabs/voltaserve/api/infra" @@ -251,7 +252,7 @@ func (svc *GroupService) Delete(id string, userID string) error { if err := svc.groupSearch.Delete([]string{group.GetID()}); err != nil { return err } - if err := svc.refreshCacheForOrganization(group.GetOrganizationID()); err != nil { + if err := svc.groupCache.Delete(group.GetID()); err != nil { return err } return nil @@ -262,24 +263,28 @@ func (svc *GroupService) AddMember(id string, memberID string, userID string) er if err != nil { return nil } - if err := svc.groupGuard.Authorize(userID, group, model.PermissionOwner); err != nil { - return err - } + + /* Ensure the member exists before proceeding. */ if _, err := svc.userRepo.Find(memberID); err != nil { return err } - if err := svc.groupRepo.AddUser(id, memberID); err != nil { - return err - } - if err := svc.groupRepo.GrantUserPermission(group.GetID(), memberID, model.PermissionViewer); err != nil { - return err - } - if _, err := svc.groupCache.Refresh(group.GetID()); err != nil { + + if err := svc.groupGuard.Authorize(userID, group, model.PermissionOwner); err != nil { return err } - if err := svc.refreshCacheForOrganization(group.GetOrganizationID()); err != nil { - return err + + /* Ensure that the member doesn't already have a higher permission on the group. + If we don't check that, we risk downgrading the existing permission.*/ + if !svc.groupGuard.IsAuthorized(memberID, group, model.PermissionViewer) && + !svc.groupGuard.IsAuthorized(memberID, group, model.PermissionEditor) { + if err := svc.groupRepo.GrantUserPermission(group.GetID(), memberID, model.PermissionViewer); err != nil { + return err + } + if _, err := svc.groupCache.Refresh(group.GetID()); err != nil { + return err + } } + return nil } @@ -288,57 +293,31 @@ func (svc *GroupService) RemoveMember(id string, memberID string, userID string) if err != nil { return nil } - if err := svc.groupGuard.Authorize(userID, group, model.PermissionOwner); err != nil { + + /* Ensure the member exists before proceeding. */ + if _, err := svc.userRepo.Find(memberID); err != nil { return err } - if err := svc.RemoveMemberUnauthorized(id, memberID); err != nil { + + if err := svc.groupGuard.Authorize(userID, group, model.PermissionOwner); err != nil { return err } - return nil -} -func (svc *GroupService) RemoveMemberUnauthorized(id string, memberID string) error { - group, err := svc.groupCache.Get(id) + /* Make sure member is not the last remaining owner of the group */ + ownerCount, err := svc.groupRepo.GetOwnerCount(group.GetID()) if err != nil { - return nil - } - if _, err := svc.userRepo.Find(memberID); err != nil { return err } - if err := svc.groupRepo.RemoveMember(id, memberID); err != nil { - return err + if svc.groupGuard.IsAuthorized(memberID, group, model.PermissionOwner) && ownerCount == 1 { + return errorpkg.NewCannotRemoveLastRemainingOwnerOfGroupError(group) } + if err := svc.groupRepo.RevokeUserPermission(id, memberID); err != nil { return err } if _, err := svc.groupCache.Refresh(group.GetID()); err != nil { return err } - if err := svc.refreshCacheForOrganization(group.GetOrganizationID()); err != nil { - return err - } - return nil -} - -func (svc *GroupService) refreshCacheForOrganization(orgID string) error { - workspaceIDs, err := svc.workspaceRepo.GetIDsByOrganization(orgID) - if err != nil { - return err - } - for _, workspaceID := range workspaceIDs { - if _, err := svc.workspaceCache.Refresh(workspaceID); err != nil { - return err - } - filesIDs, err := svc.fileRepo.GetIDsByWorkspace(workspaceID) - if err != nil { - return err - } - for _, id := range filesIDs { - if _, err := svc.fileCache.Refresh(id); err != nil { - return err - } - } - } return nil } diff --git a/api/service/invitation_service.go b/api/service/invitation_service.go index 83c8dbba0..17cbc3d15 100644 --- a/api/service/invitation_service.go +++ b/api/service/invitation_service.go @@ -77,7 +77,7 @@ func (svc *InvitationService) Create(opts InvitationCreateOptions, userID string var emails []string - /* Collect emails of non existing members and outgoing invitations */ + /* Collect emails of non-existing members and outgoing invitations */ for _, e := range opts.Emails { existing := false for _, u := range orgMembers { @@ -253,9 +253,6 @@ func (svc *InvitationService) Accept(id string, userID string) error { if err := svc.invitationRepo.Save(invitation); err != nil { return err } - if err := svc.orgRepo.AddUser(invitation.GetOrganizationID(), userID); err != nil { - return err - } if err := svc.orgRepo.GrantUserPermission(invitation.GetOrganizationID(), userID, model.PermissionViewer); err != nil { return err } diff --git a/api/service/organization_service.go b/api/service/organization_service.go index fe44528dd..b3b4c1016 100644 --- a/api/service/organization_service.go +++ b/api/service/organization_service.go @@ -27,32 +27,40 @@ import ( ) type OrganizationService struct { - orgRepo repo.OrganizationRepo - orgCache *cache.OrganizationCache - orgGuard *guard.OrganizationGuard - orgMapper *organizationMapper - orgSearch *search.OrganizationSearch - userSearch *search.UserSearch - userMapper *userMapper - groupRepo repo.GroupRepo - groupService *GroupService - groupMapper *groupMapper - config *config.Config + orgRepo repo.OrganizationRepo + orgCache *cache.OrganizationCache + orgGuard *guard.OrganizationGuard + orgMapper *organizationMapper + orgSearch *search.OrganizationSearch + userSearch *search.UserSearch + userMapper *userMapper + userRepo repo.UserRepo + groupCache *cache.GroupCache + groupRepo repo.GroupRepo + groupService *GroupService + groupMapper *groupMapper + workspaceCache *cache.WorkspaceCache + workspaceRepo repo.WorkspaceRepo + config *config.Config } func NewOrganizationService() *OrganizationService { return &OrganizationService{ - orgRepo: repo.NewOrganizationRepo(), - orgCache: cache.NewOrganizationCache(), - orgGuard: guard.NewOrganizationGuard(), - orgSearch: search.NewOrganizationSearch(), - orgMapper: newOrganizationMapper(), - userSearch: search.NewUserSearch(), - groupRepo: repo.NewGroupRepo(), - groupService: NewGroupService(), - groupMapper: newGroupMapper(), - userMapper: newUserMapper(), - config: config.GetConfig(), + orgRepo: repo.NewOrganizationRepo(), + orgCache: cache.NewOrganizationCache(), + orgGuard: guard.NewOrganizationGuard(), + orgSearch: search.NewOrganizationSearch(), + orgMapper: newOrganizationMapper(), + userSearch: search.NewUserSearch(), + userRepo: repo.NewUserRepo(), + groupCache: cache.NewGroupCache(), + groupRepo: repo.NewGroupRepo(), + groupService: NewGroupService(), + groupMapper: newGroupMapper(), + userMapper: newUserMapper(), + workspaceCache: cache.NewWorkspaceCache(), + workspaceRepo: repo.NewWorkspaceRepo(), + config: config.GetConfig(), } } @@ -220,38 +228,56 @@ func (svc *OrganizationService) RemoveMember(id string, memberID string, userID return err } + /* Ensure the member exists before proceeding. */ + if _, err := svc.userRepo.Find(memberID); err != nil { + return err + } + + if err := svc.orgGuard.Authorize(userID, org, model.PermissionOwner); err != nil { + return err + } + /* Make sure member is not the last remaining owner of the organization */ ownerCount, err := svc.orgRepo.GetOwnerCount(org.GetID()) if err != nil { return err } if svc.orgGuard.IsAuthorized(memberID, org, model.PermissionOwner) && ownerCount == 1 { - return errorpkg.NewCannotRemoveLastRemainingOwnerOfOrganizationError(org.GetID()) + return errorpkg.NewCannotRemoveLastRemainingOwnerOfOrganizationError(org) } - if userID != memberID { - if err := svc.orgGuard.Authorize(userID, org, model.PermissionOwner); err != nil { - return err + /* Revoke permissions from all groups belonging to this organization. */ + groupsIDs, err := svc.groupRepo.GetIDsByOrganization(org.GetID()) + if err != nil { + return err + } + for _, groupID := range groupsIDs { + if err := svc.groupRepo.RevokeUserPermission(groupID, memberID); err != nil { + log.GetLogger().Error(err) + } + if _, err := svc.groupCache.Refresh(groupID); err != nil { + log.GetLogger().Error(err) } } - /* Remove member from all groups belonging to this organization */ - groupsIDs, err := svc.groupRepo.GetIDsForOrganization(org.GetID()) + /* Revoke permissions from all workspaces belonging to this organization */ + workspaceIDs, err := svc.workspaceRepo.GetIDsByOrganization(org.GetID()) if err != nil { return err } - for _, groupID := range groupsIDs { - if err := svc.groupService.RemoveMemberUnauthorized(groupID, memberID); err != nil { + for _, workspaceID := range workspaceIDs { + if err := svc.workspaceRepo.RevokeUserPermission(workspaceID, memberID); err != nil { + log.GetLogger().Error(err) + } + if _, err := svc.workspaceCache.Refresh(workspaceID); err != nil { log.GetLogger().Error(err) } } + /* Revoke permission from organization */ if err := svc.orgRepo.RevokeUserPermission(id, memberID); err != nil { return err } - if err := svc.orgRepo.RemoveMember(id, memberID); err != nil { - return err - } if _, err := svc.orgCache.Refresh(org.GetID()); err != nil { return err } diff --git a/api/service/snapshot_service.go b/api/service/snapshot_service.go index 599f3cc74..5342e89fb 100644 --- a/api/service/snapshot_service.go +++ b/api/service/snapshot_service.go @@ -132,7 +132,7 @@ func (svc *SnapshotService) List(fileID string, opts SnapshotListOptions, userID if opts.SortOrder == "" { opts.SortOrder = SortOrderAsc } - ids, err := svc.snapshotRepo.GetIDsForFile(fileID) + ids, err := svc.snapshotRepo.GetIDsByFile(fileID) if err != nil { return nil, err } diff --git a/api/service/task_service.go b/api/service/task_service.go index 36c0ce1b3..98145e702 100644 --- a/api/service/task_service.go +++ b/api/service/task_service.go @@ -278,7 +278,7 @@ func (svc *TaskService) doSorting(data []model.Task, sortBy string, sortOrder st func (svc *TaskService) GetCount(userID string) (*int64, error) { var res int64 var err error - if res, err = svc.taskRepo.GetCount(userID); err != nil { + if res, err = svc.taskRepo.GetCountByEmail(userID); err != nil { return nil, err } return &res, nil diff --git a/api/service/user_service.go b/api/service/user_service.go index 6411fe10f..74a4dd9b8 100644 --- a/api/service/user_service.go +++ b/api/service/user_service.go @@ -54,7 +54,7 @@ type UserListOptions struct { Query string OrganizationID string GroupID string - NonGroupMembersOnly bool + ExcludeGroupMembers bool SortBy string SortOrder string Page uint @@ -110,7 +110,7 @@ func (svc *UserService) List(opts UserListOptions, userID string) (*UserList, er res := []model.User{} var err error if opts.Query == "" { - if opts.OrganizationID != "" && opts.GroupID != "" && opts.NonGroupMembersOnly { + if opts.OrganizationID != "" && opts.GroupID != "" && opts.ExcludeGroupMembers { orgMembers, err := svc.orgRepo.GetMembers(opts.OrganizationID) if err != nil { return nil, err @@ -120,14 +120,14 @@ func (svc *UserService) List(opts UserListOptions, userID string) (*UserList, er return nil, err } for _, om := range orgMembers { - found := false - for _, tm := range groupMembers { - if om.GetID() == tm.GetID() { - found = true + isGroupMember := false + for _, gm := range groupMembers { + if om.GetID() == gm.GetID() { + isGroupMember = true break } } - if !found { + if !isGroupMember { res = append(res, om) } } diff --git a/migrations/src/lib.rs b/migrations/src/lib.rs index 3d190ce1b..50f025f76 100644 --- a/migrations/src/lib.rs +++ b/migrations/src/lib.rs @@ -14,6 +14,8 @@ mod m20240718_000007_create_file; mod m20240718_000008_create_task; mod m20240718_000009_create_grouppermission; mod m20240718_000010_create_userpermission; +mod m20240723_000001_drop_organization_user; +mod m20240723_000002_drop_group_user; #[async_trait::async_trait] impl MigratorTrait for Migrator { @@ -29,6 +31,8 @@ impl MigratorTrait for Migrator { Box::new(m20240718_000008_create_task::Migration), Box::new(m20240718_000009_create_grouppermission::Migration), Box::new(m20240718_000010_create_userpermission::Migration), + Box::new(m20240723_000001_drop_organization_user::Migration), + Box::new(m20240723_000002_drop_group_user::Migration), ] } } diff --git a/migrations/src/m20240723_000001_drop_organization_user.rs b/migrations/src/m20240723_000001_drop_organization_user.rs new file mode 100644 index 000000000..b21eb5292 --- /dev/null +++ b/migrations/src/m20240723_000001_drop_organization_user.rs @@ -0,0 +1,24 @@ +use sea_orm_migration::prelude::*; + +use crate::models::v1::{OrganizationUser}; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up( + &self, + manager: &SchemaManager, + ) -> Result<(), DbErr> { + manager + .drop_table( + Table::drop() + .table(OrganizationUser::Table) + .to_owned(), + ) + .await?; + + Ok(()) + } +} diff --git a/migrations/src/m20240723_000002_drop_group_user.rs b/migrations/src/m20240723_000002_drop_group_user.rs new file mode 100644 index 000000000..8bde2f0fc --- /dev/null +++ b/migrations/src/m20240723_000002_drop_group_user.rs @@ -0,0 +1,24 @@ +use sea_orm_migration::prelude::*; + +use crate::models::v1::{GroupUser}; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up( + &self, + manager: &SchemaManager, + ) -> Result<(), DbErr> { + manager + .drop_table( + Table::drop() + .table(GroupUser::Table) + .to_owned(), + ) + .await?; + + Ok(()) + } +} diff --git a/ui/src/client/api/user.ts b/ui/src/client/api/user.ts index 15dcacd6c..42d92f049 100644 --- a/ui/src/client/api/user.ts +++ b/ui/src/client/api/user.ts @@ -7,7 +7,6 @@ // the Business Source License, use of this software will be governed // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. - import useSWR, { SWRConfiguration } from 'swr' import { apiFetcher } from '@/client/fetcher' @@ -41,7 +40,7 @@ export type ListOptions = { query?: string organizationId?: string groupId?: string - nonGroupMembersOnly?: boolean + excludeGroupMembers?: boolean size?: number page?: number sortBy?: SortBy @@ -56,7 +55,7 @@ type ListQueryParams = { query?: string organization_id?: string group_id?: string - non_group_members_only?: string + exclude_group_members?: string } export default class UserAPI { @@ -87,8 +86,8 @@ export default class UserAPI { if (options?.groupId) { params.group_id = options.groupId.toString() } - if (options?.nonGroupMembersOnly) { - params.non_group_members_only = options.nonGroupMembersOnly.toString() + if (options?.excludeGroupMembers) { + params.exclude_group_members = options.excludeGroupMembers.toString() } if (options?.page) { params.page = options.page.toString() diff --git a/ui/src/components/common/user-selector.tsx b/ui/src/components/common/user-selector.tsx index 367d26ee2..2d0f68d20 100644 --- a/ui/src/components/common/user-selector.tsx +++ b/ui/src/components/common/user-selector.tsx @@ -7,7 +7,6 @@ // the Business Source License, use of this software will be governed // by the GNU Affero General Public License v3.0 only, included in the file // licenses/AGPL.txt. - import { useCallback, useEffect, useState } from 'react' import { Button, @@ -62,7 +61,7 @@ const UserSelector = ({ query, organizationId, groupId, - nonGroupMembersOnly, + excludeGroupMembers: nonGroupMembersOnly, page, size: 5, sortOrder: SortOrder.Desc,