From 6a3039f7b7d635a3a3e00ea9501bc44b1c9dc76c Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 5 Feb 2023 10:37:03 +0900 Subject: feat: ロールにアイコンを設定してユーザー名の横に表示できるように MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve #9761 --- packages/backend/src/core/RoleService.ts | 13 +++++++++++++ packages/backend/src/core/entities/RoleEntityService.ts | 2 ++ packages/backend/src/core/entities/UserEntityService.ts | 6 ++++++ packages/backend/src/models/entities/Role.ts | 11 +++++++++++ .../backend/src/server/api/endpoints/admin/roles/create.ts | 6 ++++++ .../backend/src/server/api/endpoints/admin/roles/update.ts | 6 ++++++ 6 files changed, 44 insertions(+) (limited to 'packages/backend/src') diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index f8f9231cdd..d15d8c0aee 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -202,6 +202,19 @@ export class RoleService implements OnApplicationShutdown { return [...assignedRoles, ...matchedCondRoles]; } + /** + * 指定ユーザーのバッジロール一覧取得 + */ + @bindThis + public async getUserBadgeRoles(userId: User['id']) { + const assigns = await this.roleAssignmentByUserIdCache.fetch(userId, () => this.roleAssignmentsRepository.findBy({ userId })); + const assignedRoleIds = assigns.map(x => x.roleId); + const roles = await this.rolesCache.fetch(null, () => this.rolesRepository.findBy({})); + const assignedBadgeRoles = roles.filter(r => r.asBadge && assignedRoleIds.includes(r.id)); + // コンディショナルロールも含めるのは負荷高そうだから一旦無し + return assignedBadgeRoles; + } + @bindThis public async getUserPolicies(userId: User['id'] | null): Promise { const meta = await this.metaService.fetch(); diff --git a/packages/backend/src/core/entities/RoleEntityService.ts b/packages/backend/src/core/entities/RoleEntityService.ts index 52f3374468..dbb89ff19b 100644 --- a/packages/backend/src/core/entities/RoleEntityService.ts +++ b/packages/backend/src/core/entities/RoleEntityService.ts @@ -56,11 +56,13 @@ export class RoleEntityService { name: role.name, description: role.description, color: role.color, + iconUrl: role.iconUrl, target: role.target, condFormula: role.condFormula, isPublic: role.isPublic, isAdministrator: role.isAdministrator, isModerator: role.isModerator, + asBadge: role.asBadge, canEditMembersByModerator: role.canEditMembersByModerator, policies: policies, usersCount: assigns.length, diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index ff42c07359..eea9d5567d 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -415,6 +415,11 @@ export class UserEntityService implements OnModuleInit { } : undefined) : undefined, emojis: this.customEmojiService.populateEmojis(user.emojis, user.host), onlineStatus: this.getOnlineStatus(user), + // パフォーマンス上の理由でローカルユーザーのみ + badgeRoles: user.host == null ? this.roleService.getUserBadgeRoles(user.id).then(rs => rs.map(r => ({ + name: r.name, + iconUrl: r.iconUrl, + }))) : undefined, ...(opts.detail ? { url: profile!.url, @@ -454,6 +459,7 @@ export class UserEntityService implements OnModuleInit { id: role.id, name: role.name, color: role.color, + iconUrl: role.iconUrl, description: role.description, isModerator: role.isModerator, isAdministrator: role.isAdministrator, diff --git a/packages/backend/src/models/entities/Role.ts b/packages/backend/src/models/entities/Role.ts index abd5f864a2..8cf6811863 100644 --- a/packages/backend/src/models/entities/Role.ts +++ b/packages/backend/src/models/entities/Role.ts @@ -102,6 +102,11 @@ export class Role { }) public color: string | null; + @Column('varchar', { + length: 512, nullable: true, + }) + public iconUrl: string | null; + @Column('enum', { enum: ['manual', 'conditional'], default: 'manual', @@ -118,6 +123,12 @@ export class Role { }) public isPublic: boolean; + // trueの場合ユーザー名の横にバッジとして表示 + @Column('boolean', { + default: false, + }) + public asBadge: boolean; + @Column('boolean', { default: false, }) diff --git a/packages/backend/src/server/api/endpoints/admin/roles/create.ts b/packages/backend/src/server/api/endpoints/admin/roles/create.ts index f136c6d624..1a2a9fb747 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/create.ts @@ -19,11 +19,13 @@ export const paramDef = { name: { type: 'string' }, description: { type: 'string' }, color: { type: 'string', nullable: true }, + iconUrl: { type: 'string', nullable: true }, target: { type: 'string' }, condFormula: { type: 'object' }, isPublic: { type: 'boolean' }, isModerator: { type: 'boolean' }, isAdministrator: { type: 'boolean' }, + asBadge: { type: 'boolean' }, canEditMembersByModerator: { type: 'boolean' }, policies: { type: 'object', @@ -33,11 +35,13 @@ export const paramDef = { 'name', 'description', 'color', + 'iconUrl', 'target', 'condFormula', 'isPublic', 'isModerator', 'isAdministrator', + 'asBadge', 'canEditMembersByModerator', 'policies', ], @@ -64,11 +68,13 @@ export default class extends Endpoint { name: ps.name, description: ps.description, color: ps.color, + iconUrl: ps.iconUrl, target: ps.target, condFormula: ps.condFormula, isPublic: ps.isPublic, isAdministrator: ps.isAdministrator, isModerator: ps.isModerator, + asBadge: ps.asBadge, canEditMembersByModerator: ps.canEditMembersByModerator, policies: ps.policies, }).then(x => this.rolesRepository.findOneByOrFail(x.identifiers[0])); diff --git a/packages/backend/src/server/api/endpoints/admin/roles/update.ts b/packages/backend/src/server/api/endpoints/admin/roles/update.ts index fc4c3d8f11..c9f4a9fed8 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/update.ts @@ -27,11 +27,13 @@ export const paramDef = { name: { type: 'string' }, description: { type: 'string' }, color: { type: 'string', nullable: true }, + iconUrl: { type: 'string', nullable: true }, target: { type: 'string' }, condFormula: { type: 'object' }, isPublic: { type: 'boolean' }, isModerator: { type: 'boolean' }, isAdministrator: { type: 'boolean' }, + asBadge: { type: 'boolean' }, canEditMembersByModerator: { type: 'boolean' }, policies: { type: 'object', @@ -42,11 +44,13 @@ export const paramDef = { 'name', 'description', 'color', + 'iconUrl', 'target', 'condFormula', 'isPublic', 'isModerator', 'isAdministrator', + 'asBadge', 'canEditMembersByModerator', 'policies', ], @@ -73,11 +77,13 @@ export default class extends Endpoint { name: ps.name, description: ps.description, color: ps.color, + iconUrl: ps.iconUrl, target: ps.target, condFormula: ps.condFormula, isPublic: ps.isPublic, isModerator: ps.isModerator, isAdministrator: ps.isAdministrator, + asBadge: ps.asBadge, canEditMembersByModerator: ps.canEditMembersByModerator, policies: ps.policies, }); -- cgit v1.2.3-freya