diff --git a/src/lib/db/access-store.ts b/src/lib/db/access-store.ts index 69b4e06f21..1506b8f469 100644 --- a/src/lib/db/access-store.ts +++ b/src/lib/db/access-store.ts @@ -7,6 +7,7 @@ import { IAccessInfo, IAccessStore, IRole, + IRoleWithProject, IUserPermission, IUserRole, } from '../types/stores/access-store'; @@ -229,7 +230,7 @@ export class AccessStore implements IAccessStore { })); } - async getRolesForUserId(userId: number): Promise { + async getRolesForUserId(userId: number): Promise { return this.db .select(['id', 'name', 'type', 'project', 'description']) .from(T.ROLES) diff --git a/src/lib/db/project-store.ts b/src/lib/db/project-store.ts index f7d39b1f74..88af2d6e55 100644 --- a/src/lib/db/project-store.ts +++ b/src/lib/db/project-store.ts @@ -289,26 +289,28 @@ class ProjectStore implements IProjectStore { } async getProjectsByUser(userId: number): Promise { - const members = await this.db.from((db) => { - db.select('project') - .from('role_user') - .leftJoin('roles', 'role_user.role_id', 'roles.id') - .where('type', 'root') - .andWhere('name', 'Editor') - .andWhere('user_id', userId) - .union((queryBuilder) => { - queryBuilder - .select('project') - .from('group_role') - .leftJoin( - 'group_user', - 'group_user.group_id', - 'group_role.group_id', - ) - .where('user_id', userId); - }) - .as('query'); - }); + const members = await this.db + .from((db) => { + db.select('project') + .from('role_user') + .leftJoin('roles', 'role_user.role_id', 'roles.id') + .where('type', 'root') + .andWhere('name', 'Editor') + .andWhere('user_id', userId) + .union((queryBuilder) => { + queryBuilder + .select('project') + .from('group_role') + .leftJoin( + 'group_user', + 'group_user.group_id', + 'group_role.group_id', + ) + .where('user_id', userId); + }) + .as('query'); + }) + .pluck('project'); return members; } diff --git a/src/lib/openapi/spec/profile-schema.test.ts b/src/lib/openapi/spec/profile-schema.test.ts index f55c300ae3..9ff86d23bf 100644 --- a/src/lib/openapi/spec/profile-schema.test.ts +++ b/src/lib/openapi/spec/profile-schema.test.ts @@ -1,10 +1,13 @@ import { validateSchema } from '../validate'; import { ProfileSchema } from './profile-schema'; -import { RoleName } from '../../types/model'; test('profileSchema', () => { const data: ProfileSchema = { - rootRole: 'Editor' as RoleName, + rootRole: { + id: 1, + type: 'root', + name: 'Admin', + }, projects: ['default', 'secretproject'], features: [ { name: 'firstFeature', project: 'default' }, diff --git a/src/lib/openapi/spec/profile-schema.ts b/src/lib/openapi/spec/profile-schema.ts index 556e416df0..35b33e89cb 100644 --- a/src/lib/openapi/spec/profile-schema.ts +++ b/src/lib/openapi/spec/profile-schema.ts @@ -1,6 +1,6 @@ import { FromSchema } from 'json-schema-to-ts'; import { featureSchema } from './feature-schema'; -import { RoleName } from '../../types/model'; +import { roleSchema } from './role-schema'; export const profileSchema = { $id: '#/components/schemas/profileSchema', @@ -9,8 +9,7 @@ export const profileSchema = { required: ['rootRole', 'projects', 'features'], properties: { rootRole: { - type: 'string', - enum: Object.values(RoleName), + $ref: '#/components/schemas/roleSchema', }, projects: { type: 'array', @@ -28,6 +27,7 @@ export const profileSchema = { components: { schemas: { featureSchema, + roleSchema, }, }, } as const; diff --git a/src/lib/routes/admin-api/user/user.ts b/src/lib/routes/admin-api/user/user.ts index aecbb447e7..d09c53c8b8 100644 --- a/src/lib/routes/admin-api/user/user.ts +++ b/src/lib/routes/admin-api/user/user.ts @@ -21,7 +21,6 @@ import { ProfileSchema, } from '../../../openapi/spec/profile-schema'; import ProjectService from '../../../services/project-service'; -import { RoleName } from '../../../types/model'; class UserController extends Controller { private accessService: AccessService; @@ -148,10 +147,10 @@ class UserController extends Controller { const projects = await this.projectService.getProjectsByUser(user.id); const roles = await this.accessService.getUserRootRoles(user.id); - + const { project, ...rootRole } = roles[0]; const responseData: ProfileSchema = { projects, - rootRole: roles[0].name as RoleName, + rootRole, features: [], }; diff --git a/src/lib/services/access-service.ts b/src/lib/services/access-service.ts index 36266b44ce..4896f95103 100644 --- a/src/lib/services/access-service.ts +++ b/src/lib/services/access-service.ts @@ -5,6 +5,7 @@ import { IAccessStore, IRole, IRoleWithPermissions, + IRoleWithProject, IUserPermission, IUserRole, } from '../types/stores/access-store'; @@ -243,7 +244,7 @@ export class AccessService { } } - async getUserRootRoles(userId: number): Promise { + async getUserRootRoles(userId: number): Promise { const userRoles = await this.store.getRolesForUserId(userId); return userRoles.filter((r) => r.type === RoleType.ROOT); } diff --git a/src/lib/types/stores/access-store.ts b/src/lib/types/stores/access-store.ts index 4813f95ddc..8b8a2cea52 100644 --- a/src/lib/types/stores/access-store.ts +++ b/src/lib/types/stores/access-store.ts @@ -14,6 +14,10 @@ export interface IRole { type: string; } +export interface IRoleWithProject extends IRole { + project: string; +} + export interface IRoleWithPermissions extends IRole { permissions: IPermission[]; } @@ -49,7 +53,7 @@ export interface IAccessStore extends Store { unlinkUserRoles(userId: number): Promise; - getRolesForUserId(userId: number): Promise; + getRolesForUserId(userId: number): Promise; getProjectUsersForRole( roleId: number, diff --git a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap index 84343706b5..4acf2c079a 100644 --- a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap +++ b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap @@ -2167,14 +2167,7 @@ exports[`should serve the OpenAPI spec 1`] = ` "type": "array", }, "rootRole": { - "enum": [ - "Admin", - "Editor", - "Viewer", - "Owner", - "Member", - ], - "type": "string", + "$ref": "#/components/schemas/roleSchema", }, }, "required": [ diff --git a/src/test/fixtures/fake-access-store.ts b/src/test/fixtures/fake-access-store.ts index 805d646c60..92a6717dc1 100644 --- a/src/test/fixtures/fake-access-store.ts +++ b/src/test/fixtures/fake-access-store.ts @@ -4,10 +4,11 @@ import { IAccessInfo, IAccessStore, IRole, + IRoleWithProject, IUserPermission, IUserRole, } from '../../lib/types/stores/access-store'; -import { IAvailablePermissions, IPermission } from 'lib/types/model'; +import { IPermission } from 'lib/types/model'; class AccessStoreMock implements IAccessStore { addAccessToProject( @@ -123,7 +124,7 @@ class AccessStoreMock implements IAccessStore { throw new Error('Method not implemented.'); } - getRolesForUserId(userId: number): Promise { + getRolesForUserId(userId: number): Promise { return Promise.resolve([]); }