From f3a16bcd6d220059a02ab1e1b5e72a27c5e0eba7 Mon Sep 17 00:00:00 2001
From: nenohi <kimutipartylove@gmail.com>
Date: Sat, 10 Jun 2023 17:26:48 +0900
Subject: [PATCH] =?UTF-8?q?=E3=83=AD=E3=83=BC=E3=83=AB=E3=81=AE=E3=83=A6?=
 =?UTF-8?q?=E3=83=BC=E3=82=B6=E3=83=BC=E3=83=AA=E3=82=B9=E3=83=88=E3=82=92?=
 =?UTF-8?q?=E9=9D=9E=E5=85=AC=E9=96=8B=E3=81=AB=E3=81=A7=E3=81=8D=E3=82=8B?=
 =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=20(#10987)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* ロールのユーザーリストを非公開にできるように

* Changelog update
---
 CHANGELOG.md                                          | 11 +++++++++++
 locales/index.d.ts                                    |  2 ++
 locales/ja-JP.yml                                     |  4 +++-
 .../backend/migration/1686381571997-roleuserhidden.js | 11 +++++++++++
 packages/backend/src/models/entities/Role.ts          |  5 +++++
 .../src/server/api/endpoints/admin/roles/create.ts    |  2 ++
 .../src/server/api/endpoints/admin/roles/update.ts    |  2 ++
 .../backend/src/server/api/endpoints/roles/users.ts   |  3 +++
 packages/frontend/src/pages/admin/roles.editor.vue    |  6 ++++++
 9 files changed, 45 insertions(+), 1 deletion(-)
 create mode 100644 packages/backend/migration/1686381571997-roleuserhidden.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9806e0305c..55dab31d38 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,17 @@
 -
 
 -->
+## 13.x.x (unreleased)
+
+### General
+- ロールが付与されているユーザーリストを非公開にできるように
+
+### Client
+-
+
+### Server
+-
+
 
 ## 13.13.1
 
diff --git a/locales/index.d.ts b/locales/index.d.ts
index eed29f408c..638ac10e71 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -1431,6 +1431,8 @@ export interface Locale {
         "isConditionalRole": string;
         "isPublic": string;
         "descriptionOfIsPublic": string;
+        "isPublicUsers": string;
+        "descriptionOfIsPublicUsers": string;
         "options": string;
         "policies": string;
         "baseRole": string;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 723d0ac988..5a7a2afd5f 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1353,7 +1353,9 @@ _role:
   condition: "条件"
   isConditionalRole: "これはコンディショナルロールです。"
   isPublic: "ロールを公開"
-  descriptionOfIsPublic: "ロールにアサインされたユーザーを誰でも見ることができます。また、ユーザーのプロフィールでこのロールが表示されます。"
+  descriptionOfIsPublic: "ユーザーのプロフィールでこのロールが表示されます。"
+  isPublicUsers: "ユーザーリストを公開"
+  descriptionOfIsPublicUsers: "ロールにアサインされたユーザーのリストを誰でも見ることができます。"
   options: "オプション"
   policies: "ポリシー"
   baseRole: "ベースロール"
diff --git a/packages/backend/migration/1686381571997-roleuserhidden.js b/packages/backend/migration/1686381571997-roleuserhidden.js
new file mode 100644
index 0000000000..5cfa9ab87f
--- /dev/null
+++ b/packages/backend/migration/1686381571997-roleuserhidden.js
@@ -0,0 +1,11 @@
+export class roleuserhidden1686381571997 {
+    name = 'roleuserhidden1686381571997'
+
+    async up(queryRunner) {
+        await queryRunner.query(`ALTER TABLE "role" ADD "isPublicUsers" boolean NOT NULL DEFAULT true`);
+    }
+
+    async down(queryRunner) {
+        await queryRunner.query(`ALTER TABLE "role" DROP COLUMN "isPublicUsers"`);
+     }
+}
diff --git a/packages/backend/src/models/entities/Role.ts b/packages/backend/src/models/entities/Role.ts
index 61f40d59da..067f7bf629 100644
--- a/packages/backend/src/models/entities/Role.ts
+++ b/packages/backend/src/models/entities/Role.ts
@@ -167,6 +167,11 @@ export class Role {
 	})
 	public displayOrder: number;
 
+	@Column('boolean', {
+		default: true,
+	})
+	public isPublicUsers: boolean;
+
 	@Column('jsonb', {
 		default: { },
 	})
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 916172f54a..1cf3157acd 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/create.ts
@@ -26,6 +26,7 @@ export const paramDef = {
 		isModerator: { type: 'boolean' },
 		isAdministrator: { type: 'boolean' },
 		isExplorable: { type: 'boolean', default: false }, // optional for backward compatibility
+		isPublicUsers: { type: 'boolean', default: true }, // optional for backward compatibility
 		asBadge: { type: 'boolean' },
 		canEditMembersByModerator: { type: 'boolean' },
 		displayOrder: { type: 'number' },
@@ -78,6 +79,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				isAdministrator: ps.isAdministrator,
 				isModerator: ps.isModerator,
 				isExplorable: ps.isExplorable,
+				isPublicUsers: ps.isPublicUsers,
 				asBadge: ps.asBadge,
 				canEditMembersByModerator: ps.canEditMembersByModerator,
 				displayOrder: ps.displayOrder,
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 467f157a61..5108c4da1d 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/update.ts
@@ -34,6 +34,7 @@ export const paramDef = {
 		isModerator: { type: 'boolean' },
 		isAdministrator: { type: 'boolean' },
 		isExplorable: { type: 'boolean' },
+		isPublicUsers: { type: 'boolean' },
 		asBadge: { type: 'boolean' },
 		canEditMembersByModerator: { type: 'boolean' },
 		displayOrder: { type: 'number' },
@@ -87,6 +88,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 				isModerator: ps.isModerator,
 				isAdministrator: ps.isAdministrator,
 				isExplorable: ps.isExplorable,
+				isPublicUsers: ps.isPublicUsers,
 				asBadge: ps.asBadge,
 				canEditMembersByModerator: ps.canEditMembersByModerator,
 				displayOrder: ps.displayOrder,
diff --git a/packages/backend/src/server/api/endpoints/roles/users.ts b/packages/backend/src/server/api/endpoints/roles/users.ts
index 607dc24206..f4b30286a4 100644
--- a/packages/backend/src/server/api/endpoints/roles/users.ts
+++ b/packages/backend/src/server/api/endpoints/roles/users.ts
@@ -54,6 +54,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 			if (role == null) {
 				throw new ApiError(meta.errors.noSuchRole);
 			}
+			if (!role.isPublicUsers) {
+				return [];
+			}
 
 			const query = this.queryService.makePaginationQuery(this.roleAssignmentsRepository.createQueryBuilder('assign'), ps.sinceId, ps.untilId)
 				.andWhere('assign.roleId = :roleId', { roleId: role.id })
diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue
index a1fa9d2932..6aeef6cb1d 100644
--- a/packages/frontend/src/pages/admin/roles.editor.vue
+++ b/packages/frontend/src/pages/admin/roles.editor.vue
@@ -63,6 +63,11 @@
 		<template #caption>{{ i18n.ts._role.descriptionOfIsExplorable }}</template>
 	</MkSwitch>
 
+	<MkSwitch v-model="role.isPublicUsers" :readonly="readonly">
+		<template #label>{{ i18n.ts._role.isPublicUsers }}</template>
+		<template #caption>{{ i18n.ts._role.descriptionOfIsPublicUsers }}</template>
+	</MkSwitch>
+
 	<FormSlot>
 		<template #label><i class="ti ti-license"></i> {{ i18n.ts._role.policies }}</template>
 		<div class="_gaps_s">
@@ -501,6 +506,7 @@ const save = throttle(100, () => {
 		isModerator: role.isModerator,
 		isPublic: role.isPublic,
 		isExplorable: role.isExplorable,
+		isPublicUsers: role.isPublicUsers,
 		asBadge: role.asBadge,
 		canEditMembersByModerator: role.canEditMembersByModerator,
 		policies: role.policies,