feat: ロールでアップロード可能なファイル種別を設定可能に (#16081)

* wip

* Update RoleService.ts

* wip

* Update RoleService.ts

* Update CHANGELOG.md
This commit is contained in:
syuilo
2025-05-22 23:01:31 +09:00
committed by GitHub
parent aaee0a788d
commit e750c9171e
12 changed files with 118 additions and 6 deletions

View File

@@ -515,16 +515,23 @@ export class DriveService {
this.registerLogger.debug(`ADD DRIVE FILE: user ${user?.id ?? 'not set'}, name ${detectedName}, tmp ${path}`);
//#region Check drive usage
//#region Check drive usage and mime type
if (user && !isLink) {
const usage = await this.driveFileEntityService.calcDriveUsageOf(user);
const isLocalUser = this.userEntityService.isLocalUser(user);
const policies = await this.roleService.getUserPolicies(user.id);
const allowedMimeTypes = policies.uploadableFileTypes;
const isAllowed = allowedMimeTypes.some((mimeType) => {
if (mimeType === '*' || mimeType === '*/*') return true;
if (mimeType.endsWith('/*')) return info.type.mime.startsWith(mimeType.slice(0, -1));
return info.type.mime === mimeType;
});
if (!isAllowed) {
throw new IdentifiableError('bd71c601-f9b0-4808-9137-a330647ced9b', 'Unallowed file type.');
}
const driveCapacity = 1024 * 1024 * policies.driveCapacityMb;
const maxFileSize = 1024 * 1024 * policies.maxFileSizeMb;
this.registerLogger.debug('drive capacity override applied');
this.registerLogger.debug(`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${usage + info.size}bytes`);
if (maxFileSize < info.size) {
if (isLocalUser) {
@@ -532,6 +539,11 @@ export class DriveService {
}
}
const usage = await this.driveFileEntityService.calcDriveUsageOf(user);
this.registerLogger.debug('drive capacity override applied');
this.registerLogger.debug(`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${usage + info.size}bytes`);
// If usage limit exceeded
if (driveCapacity < usage + info.size) {
if (isLocalUser) {

View File

@@ -65,6 +65,7 @@ export type RolePolicies = {
canImportMuting: boolean;
canImportUserLists: boolean;
chatAvailability: 'available' | 'readonly' | 'unavailable';
uploadableFileTypes: string[];
};
export const DEFAULT_POLICIES: RolePolicies = {
@@ -101,6 +102,13 @@ export const DEFAULT_POLICIES: RolePolicies = {
canImportMuting: true,
canImportUserLists: true,
chatAvailability: 'available',
uploadableFileTypes: [
'text/plain',
'application/json',
'image/*',
'video/*',
'audio/*',
],
};
@Injectable()
@@ -412,6 +420,16 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
canImportMuting: calc('canImportMuting', vs => vs.some(v => v === true)),
canImportUserLists: calc('canImportUserLists', vs => vs.some(v => v === true)),
chatAvailability: calc('chatAvailability', aggregateChatAvailability),
uploadableFileTypes: calc('uploadableFileTypes', vs => {
const set = new Set<string>();
for (const v of vs) {
for (const type of v) {
if (type.trim() === '') continue;
set.add(type.trim());
}
}
return [...set];
}),
};
}

View File

@@ -228,6 +228,14 @@ export const packedRolePoliciesSchema = {
type: 'integer',
optional: false, nullable: false,
},
uploadableFileTypes: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'string',
optional: false, nullable: false,
},
},
alwaysMarkNsfw: {
type: 'boolean',
optional: false, nullable: false,