summaryrefslogtreecommitdiff
path: root/packages/backend
diff options
context:
space:
mode:
authornenohi <kimutipartylove@gmail.com>2023-05-05 14:18:06 +0900
committerGitHub <noreply@github.com>2023-05-05 14:18:06 +0900
commit2d84e042405322fc7f9dd5955f9d72f59cdb3a81 (patch)
tree4fc0725045c36b6937c49e363f17be7758c36b64 /packages/backend
parentMerge branch 'develop' of https://github.com/misskey-dev/misskey into develop (diff)
downloadmisskey-2d84e042405322fc7f9dd5955f9d72f59cdb3a81.tar.gz
misskey-2d84e042405322fc7f9dd5955f9d72f59cdb3a81.tar.bz2
misskey-2d84e042405322fc7f9dd5955f9d72f59cdb3a81.zip
ロールにNSFWを強制的につけるオプションを追加 (#10731)
* ロールにNSFWを強制的につけるオプションを追加 * すでにあるファイルにNSFWが付与できない * NSFWを付与しようとするとエラーに * add test * Update packages/backend/src/core/RoleService.ts Co-authored-by: syuilo <Syuilotan@yahoo.co.jp> * spacingで怒られたので * ロール作成時のプロパティ削除 --------- Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Diffstat (limited to 'packages/backend')
-rw-r--r--packages/backend/src/core/DriveService.ts8
-rw-r--r--packages/backend/src/core/RoleService.ts3
-rw-r--r--packages/backend/src/core/activitypub/models/ApNoteService.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/drive/files/update.ts13
-rw-r--r--packages/backend/src/server/api/endpoints/i/update.ts11
-rw-r--r--packages/backend/test/e2e/note.ts66
6 files changed, 98 insertions, 5 deletions
diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts
index 7f66f1137f..1483b55469 100644
--- a/packages/backend/src/core/DriveService.ts
+++ b/packages/backend/src/core/DriveService.ts
@@ -449,7 +449,12 @@ export class DriveService {
}: AddFileArgs): Promise<DriveFile> {
let skipNsfwCheck = false;
const instance = await this.metaService.fetch();
- if (user == null) skipNsfwCheck = true;
+ const userRoleNSFW = user && (await this.roleService.getUserPolicies(user.id)).alwaysMarkNsfw;
+ if (user == null) {
+ skipNsfwCheck = true;
+ } else if (userRoleNSFW) {
+ skipNsfwCheck = true;
+ }
if (instance.sensitiveMediaDetection === 'none') skipNsfwCheck = true;
if (user && instance.sensitiveMediaDetection === 'local' && this.userEntityService.isRemoteUser(user)) skipNsfwCheck = true;
if (user && instance.sensitiveMediaDetection === 'remote' && this.userEntityService.isLocalUser(user)) skipNsfwCheck = true;
@@ -571,6 +576,7 @@ export class DriveService {
if (info.sensitive && profile!.autoSensitive) file.isSensitive = true;
if (info.sensitive && instance.setSensitiveFlagAutomatically) file.isSensitive = true;
+ if (userRoleNSFW) file.isSensitive = true;
if (url !== null) {
file.src = url;
diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts
index 3878c147d0..68087ccc3b 100644
--- a/packages/backend/src/core/RoleService.ts
+++ b/packages/backend/src/core/RoleService.ts
@@ -25,6 +25,7 @@ export type RolePolicies = {
canSearchNotes: boolean;
canHideAds: boolean;
driveCapacityMb: number;
+ alwaysMarkNsfw: boolean;
pinLimit: number;
antennaLimit: number;
wordMuteLimit: number;
@@ -45,6 +46,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
canSearchNotes: false,
canHideAds: false,
driveCapacityMb: 100,
+ alwaysMarkNsfw: false,
pinLimit: 5,
antennaLimit: 5,
wordMuteLimit: 200,
@@ -279,6 +281,7 @@ export class RoleService implements OnApplicationShutdown {
canSearchNotes: calc('canSearchNotes', vs => vs.some(v => v === true)),
canHideAds: calc('canHideAds', vs => vs.some(v => v === true)),
driveCapacityMb: calc('driveCapacityMb', vs => Math.max(...vs)),
+ alwaysMarkNsfw: calc('alwaysMarkNsfw', vs => vs.some(v => v === true)),
pinLimit: calc('pinLimit', vs => Math.max(...vs)),
antennaLimit: calc('antennaLimit', vs => Math.max(...vs)),
wordMuteLimit: calc('wordMuteLimit', vs => Math.max(...vs)),
diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts
index a9a1f926d2..87a9db405f 100644
--- a/packages/backend/src/core/activitypub/models/ApNoteService.ts
+++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts
@@ -150,7 +150,7 @@ export class ApNoteService {
if (actor.isSuspended) {
throw new Error('actor has been suspended');
}
-
+
const noteAudience = await this.apAudienceService.parseAudience(actor, note.to, note.cc, resolver);
let visibility = noteAudience.visibility;
const visibleUsers = noteAudience.visibleUsers;
diff --git a/packages/backend/src/server/api/endpoints/drive/files/update.ts b/packages/backend/src/server/api/endpoints/drive/files/update.ts
index 3141e0fc01..3ecbba22b5 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/update.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/update.ts
@@ -40,8 +40,13 @@ export const meta = {
code: 'NO_SUCH_FOLDER',
id: 'ea8fb7a5-af77-4a08-b608-c0218176cd73',
},
+
+ restrictedByRole: {
+ message: 'This feature is restricted by your role.',
+ code: 'RESTRICTED_BY_ROLE',
+ id: '7f59dccb-f465-75ab-5cf4-3ce44e3282f7',
+ },
},
-
res: {
type: 'object',
optional: false, nullable: false,
@@ -77,7 +82,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
) {
super(meta, paramDef, async (ps, me) => {
const file = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
-
+ const alwaysMarkNsfw = (await this.roleService.getUserPolicies(me.id)).alwaysMarkNsfw;
if (file == null) {
throw new ApiError(meta.errors.noSuchFile);
}
@@ -93,6 +98,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (ps.comment !== undefined) file.comment = ps.comment;
+ if (ps.isSensitive !== undefined && ps.isSensitive !== file.isSensitive && alwaysMarkNsfw && !ps.isSensitive) {
+ throw new ApiError(meta.errors.restrictedByRole);
+ }
+
if (ps.isSensitive !== undefined) file.isSensitive = ps.isSensitive;
if (ps.folderId !== undefined) {
diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index 738edf3978..6c66300bb7 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -93,6 +93,12 @@ export const meta = {
code: 'FORBIDDEN_TO_SET_YOURSELF',
id: '25c90186-4ab0-49c8-9bba-a1fa6c202ba4',
},
+
+ restrictedByRole: {
+ message: 'This feature is restricted by your role.',
+ code: 'RESTRICTED_BY_ROLE',
+ id: '8feff0ba-5ab5-585b-31f4-4df816663fad',
+ }
},
res: {
@@ -239,7 +245,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (typeof ps.isCat === 'boolean') updates.isCat = ps.isCat;
if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote;
if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail;
- if (typeof ps.alwaysMarkNsfw === 'boolean') profileUpdates.alwaysMarkNsfw = ps.alwaysMarkNsfw;
+ if (typeof ps.alwaysMarkNsfw === 'boolean') {
+ if ((await roleService.getUserPolicies(user.id)).alwaysMarkNsfw) throw new ApiError(meta.errors.restrictedByRole);
+ profileUpdates.alwaysMarkNsfw = ps.alwaysMarkNsfw;
+ }
if (typeof ps.autoSensitive === 'boolean') profileUpdates.autoSensitive = ps.autoSensitive;
if (ps.emailNotificationTypes !== undefined) profileUpdates.emailNotificationTypes = ps.emailNotificationTypes;
diff --git a/packages/backend/test/e2e/note.ts b/packages/backend/test/e2e/note.ts
index e87045a8cf..9c851a5dd6 100644
--- a/packages/backend/test/e2e/note.ts
+++ b/packages/backend/test/e2e/note.ts
@@ -352,6 +352,72 @@ describe('Note', () => {
assert.strictEqual(myNote.renote.reply.files.length, 1);
assert.strictEqual(myNote.renote.reply.files[0].id, file.body.id);
});
+
+ test('NSFWが強制されている場合変更できない', async () => {
+ const file = await uploadFile(alice);
+
+ const res = await api('admin/roles/create', {
+ name: 'test',
+ description: '',
+ color: null,
+ iconUrl: null,
+ displayOrder: 0,
+ target: 'manual',
+ condFormula: {},
+ isAdministrator: false,
+ isModerator: false,
+ isPublic: false,
+ isExplorable: false,
+ asBadge: false,
+ canEditMembersByModerator: false,
+ policies: {
+ alwaysMarkNsfw: {
+ useDefault: false,
+ priority: 0,
+ value: true,
+ },
+ },
+ }, alice);
+
+ assert.strictEqual(res.status, 200);
+
+ const assign = await api('admin/roles/assign', {
+ userId: alice.id,
+ roleId: res.body.id,
+ }, alice);
+
+ assert.strictEqual(assign.status, 204);
+ assert.strictEqual(file.body.isSensitive, false);
+
+ const nsfwfile = await uploadFile(alice);
+
+ assert.strictEqual(nsfwfile.status, 200);
+ assert.strictEqual(nsfwfile.body.isSensitive, true);
+
+ const liftnsfw = await api('drive/files/update', {
+ fileId: nsfwfile.body.id,
+ isSensitive: false,
+ }, alice);
+
+ assert.strictEqual(liftnsfw.status, 400);
+ assert.strictEqual(liftnsfw.body.error.code, 'RESTRICTED_BY_ROLE');
+
+ const oldaddnsfw = await api('drive/files/update', {
+ fileId: file.body.id,
+ isSensitive: true,
+ }, alice);
+
+ assert.strictEqual(oldaddnsfw.status, 200);
+
+ await api('admin/roles/unassign', {
+ userId: alice.id,
+ roleId: res.body.id,
+ });
+
+ await api('admin/roles/delete', {
+ roleId: res.body.id,
+ }, alice);
+ });
});
describe('notes/create', () => {