移行作業再開

This commit is contained in:
tamaina 2023-06-16 06:40:54 +00:00
parent 27b6921d3c
commit 028e7c00ae
7 changed files with 246 additions and 241 deletions

View file

@ -7,41 +7,10 @@ import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js'; import { RoleService } from '@/core/RoleService.js';
import { ApiError } from '../../../error.js'; import { ApiError } from '../../../error.js';
export const meta = {
tags: ['drive'],
requireCredential: true,
kind: 'write:drive',
description: 'Delete an existing drive file.',
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: '908939ec-e52b-4458-b395-1025195cea58',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '5eb8d909-2540-4970-90b8-dd6f86088121',
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
},
required: ['fileId'],
} as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@Injectable() @Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { export default class extends Endpoint<'drive/files/delete'> {
name = 'drive/files/delete' as const;
constructor( constructor(
@Inject(DI.driveFilesRepository) @Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository, private driveFilesRepository: DriveFilesRepository,
@ -50,15 +19,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private roleService: RoleService, private roleService: RoleService,
private globalEventService: GlobalEventService, private globalEventService: GlobalEventService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(async (ps, me) => {
const file = await this.driveFilesRepository.findOneBy({ id: ps.fileId }); const file = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
if (file == null) { if (file == null) {
throw new ApiError(meta.errors.noSuchFile); throw new ApiError(this.meta.errors.noSuchFile);
} }
if (!await this.roleService.isModerator(me) && (file.userId !== me.id)) { if (!await this.roleService.isModerator(me) && (file.userId !== me.id)) {
throw new ApiError(meta.errors.accessDenied); throw new ApiError(this.meta.errors.accessDenied);
} }
// Delete // Delete

View file

@ -4,44 +4,17 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
export const meta = {
tags: ['drive'],
requireCredential: true,
kind: 'read:drive',
description: 'Search for a drive file by a hash of the contents.',
res: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'object',
optional: false, nullable: false,
ref: 'DriveFile',
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
md5: { type: 'string' },
},
required: ['md5'],
} as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@Injectable() @Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { export default class extends Endpoint<'drive/files/find-by-hash'> {
name = 'drive/files/find-by-hash' as const;
constructor( constructor(
@Inject(DI.driveFilesRepository) @Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository, private driveFilesRepository: DriveFilesRepository,
private driveFileEntityService: DriveFileEntityService, private driveFileEntityService: DriveFileEntityService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(async (ps, me) => {
const files = await this.driveFilesRepository.findBy({ const files = await this.driveFilesRepository.findBy({
md5: ps.md5, md5: ps.md5,
userId: me.id, userId: me.id,

View file

@ -5,45 +5,17 @@ import type { DriveFilesRepository } from '@/models/index.js';
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
export const meta = {
requireCredential: true,
tags: ['drive'],
kind: 'read:drive',
description: 'Search for a drive file by the given parameters.',
res: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'object',
optional: false, nullable: false,
ref: 'DriveFile',
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
name: { type: 'string' },
folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null },
},
required: ['name'],
} as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@Injectable() @Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { export default class extends Endpoint<'drive/files/find'> {
name = 'drive/files/find' as const;
constructor( constructor(
@Inject(DI.driveFilesRepository) @Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository, private driveFilesRepository: DriveFilesRepository,
private driveFileEntityService: DriveFileEntityService, private driveFileEntityService: DriveFileEntityService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(async (ps, me) => {
const files = await this.driveFilesRepository.findBy({ const files = await this.driveFilesRepository.findBy({
name: ps.name, name: ps.name,
userId: me.id, userId: me.id,

View file

@ -7,51 +7,10 @@ import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js'; import { RoleService } from '@/core/RoleService.js';
import { ApiError } from '../../../error.js'; import { ApiError } from '../../../error.js';
export const meta = {
tags: ['drive'],
requireCredential: true,
kind: 'read:drive',
description: 'Show the properties of a drive file.',
res: {
type: 'object',
optional: false, nullable: false,
ref: 'DriveFile',
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: '067bc436-2718-4795-b0fb-ecbe43949e31',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '25b73c73-68b1-41d0-bad1-381cfdf6579f',
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
url: { type: 'string' },
},
anyOf: [
{ required: ['fileId'] },
{ required: ['url'] },
],
} as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@Injectable() @Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { export default class extends Endpoint<'drive/files/show'> {
name = 'drive/files/show' as const;
constructor( constructor(
@Inject(DI.driveFilesRepository) @Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository, private driveFilesRepository: DriveFilesRepository,
@ -59,7 +18,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private driveFileEntityService: DriveFileEntityService, private driveFileEntityService: DriveFileEntityService,
private roleService: RoleService, private roleService: RoleService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(async (ps, me) => {
let file: DriveFile | null = null; let file: DriveFile | null = null;
if (ps.fileId) { if (ps.fileId) {
@ -77,11 +36,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
} }
if (file == null) { if (file == null) {
throw new ApiError(meta.errors.noSuchFile); throw new ApiError(this.meta.errors.noSuchFile);
} }
if (!await this.roleService.isModerator(me) && (file.userId !== me.id)) { if (!await this.roleService.isModerator(me) && (file.userId !== me.id)) {
throw new ApiError(meta.errors.accessDenied); throw new ApiError(this.meta.errors.accessDenied);
} }
return await this.driveFileEntityService.pack(file, { return await this.driveFileEntityService.pack(file, {

View file

@ -7,68 +7,10 @@ import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js'; import { RoleService } from '@/core/RoleService.js';
import { ApiError } from '../../../error.js'; import { ApiError } from '../../../error.js';
export const meta = {
tags: ['drive'],
requireCredential: true,
kind: 'write:drive',
description: 'Update the properties of a drive file.',
errors: {
invalidFileName: {
message: 'Invalid file name.',
code: 'INVALID_FILE_NAME',
id: '395e7156-f9f0-475e-af89-53c3c23080c2',
},
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'e7778c7e-3af9-49cd-9690-6dbc3e6c972d',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '01a53b27-82fc-445b-a0c1-b558465a8ed2',
},
noSuchFolder: {
message: 'No such folder.',
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,
ref: 'DriveFile',
},
} as const;
export const paramDef = {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
folderId: { type: 'string', format: 'misskey:id', nullable: true },
name: { type: 'string' },
isSensitive: { type: 'boolean' },
comment: { type: 'string', nullable: true, maxLength: 512 },
},
required: ['fileId'],
} as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@Injectable() @Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { export default class extends Endpoint<'drive/files/update'> {
name = 'drive/files/update' as const;
constructor( constructor(
@Inject(DI.driveFilesRepository) @Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository, private driveFilesRepository: DriveFilesRepository,
@ -80,26 +22,26 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private roleService: RoleService, private roleService: RoleService,
private globalEventService: GlobalEventService, private globalEventService: GlobalEventService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(async (ps, me) => {
const file = await this.driveFilesRepository.findOneBy({ id: ps.fileId }); const file = await this.driveFilesRepository.findOneBy({ id: ps.fileId });
const alwaysMarkNsfw = (await this.roleService.getUserPolicies(me.id)).alwaysMarkNsfw; const alwaysMarkNsfw = (await this.roleService.getUserPolicies(me.id)).alwaysMarkNsfw;
if (file == null) { if (file == null) {
throw new ApiError(meta.errors.noSuchFile); throw new ApiError(this.meta.errors.noSuchFile);
} }
if (!await this.roleService.isModerator(me) && (file.userId !== me.id)) { if (!await this.roleService.isModerator(me) && (file.userId !== me.id)) {
throw new ApiError(meta.errors.accessDenied); throw new ApiError(this.meta.errors.accessDenied);
} }
if (ps.name) file.name = ps.name; if (ps.name) file.name = ps.name;
if (!this.driveFileEntityService.validateFileName(file.name)) { if (!this.driveFileEntityService.validateFileName(file.name)) {
throw new ApiError(meta.errors.invalidFileName); throw new ApiError(this.meta.errors.invalidFileName);
} }
if (ps.comment !== undefined) file.comment = ps.comment; if (ps.comment !== undefined) file.comment = ps.comment;
if (ps.isSensitive !== undefined && ps.isSensitive !== file.isSensitive && alwaysMarkNsfw && !ps.isSensitive) { if (ps.isSensitive !== undefined && ps.isSensitive !== file.isSensitive && alwaysMarkNsfw && !ps.isSensitive) {
throw new ApiError(meta.errors.restrictedByRole); throw new ApiError(this.meta.errors.restrictedByRole);
} }
if (ps.isSensitive !== undefined) file.isSensitive = ps.isSensitive; if (ps.isSensitive !== undefined) file.isSensitive = ps.isSensitive;
@ -114,7 +56,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
}); });
if (folder == null) { if (folder == null) {
throw new ApiError(meta.errors.noSuchFolder); throw new ApiError(this.meta.errors.noSuchFolder);
} }
file.folderId = folder.id; file.folderId = folder.id;

View file

@ -7,39 +7,10 @@ import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.j
import { DriveService } from '@/core/DriveService.js'; import { DriveService } from '@/core/DriveService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
export const meta = {
tags: ['drive'],
limit: {
duration: ms('1hour'),
max: 60,
},
description: 'Request the server to download a new drive file from the specified URL.',
requireCredential: true,
prohibitMoved: true,
kind: 'write:drive',
} as const;
export const paramDef = {
type: 'object',
properties: {
url: { type: 'string' },
folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null },
isSensitive: { type: 'boolean', default: false },
comment: { type: 'string', nullable: true, maxLength: 512, default: null },
marker: { type: 'string', nullable: true, default: null },
force: { type: 'boolean', default: false },
},
required: ['url'],
} as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@Injectable() @Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { export default class extends Endpoint<'drive/files/upload-from-url'> {
name = 'drive/files/upload-from-url' as const;
constructor( constructor(
@Inject(DI.driveFilesRepository) @Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository, private driveFilesRepository: DriveFilesRepository,
@ -48,7 +19,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private driveService: DriveService, private driveService: DriveService,
private globalEventService: GlobalEventService, private globalEventService: GlobalEventService,
) { ) {
super(meta, paramDef, async (ps, user, _1, _2, _3, ip, headers) => { super(async (ps, user, _1, _2, _3, ip, headers) => {
this.driveService.uploadFromUrl({ url: ps.url, user, folderId: ps.folderId, sensitive: ps.isSensitive, force: ps.force, comment: ps.comment, requestIp: ip, requestHeaders: headers }).then(file => { this.driveService.uploadFromUrl({ url: ps.url, user, folderId: ps.folderId, sensitive: ps.isSensitive, force: ps.force, comment: ps.comment, requestIp: ip, requestHeaders: headers }).then(file => {
this.driveFileEntityService.pack(file, { self: true }).then(packedFile => { this.driveFileEntityService.pack(file, { self: true }).then(packedFile => {
this.globalEventService.publishMainStream(user.id, 'urlUploadFinished', { this.globalEventService.publishMainStream(user.id, 'urlUploadFinished', {

View file

@ -3695,6 +3695,225 @@ export const endpoints = {
}, },
}], }],
}, },
'drive/files/delete': {
tags: ['drive'],
requireCredential: true,
kind: 'write:drive',
description: 'Delete an existing drive file.',
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: '908939ec-e52b-4458-b395-1025195cea58',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '5eb8d909-2540-4970-90b8-dd6f86088121',
},
},
defines: [{
req: {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
},
required: ['fileId'],
},
res: undefined,
}],
},
'drive/files/find-by-hash': {
tags: ['drive'],
requireCredential: true,
kind: 'read:drive',
description: 'Search for a drive file by a hash of the contents.',
defines: [{
req: {
type: 'object',
properties: {
md5: { type: 'string' },
},
required: ['md5'],
},
res: {
type: 'array',
items: {
$ref: 'https://misskey-hub.net/api/schemas/DriveFile',
},
},
}],
},
'drive/files/find': {
requireCredential: true,
tags: ['drive'],
kind: 'read:drive',
description: 'Search for a drive file by the given parameters.',
defines: [{
req: {
type: 'object',
properties: {
name: { type: 'string' },
folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null },
},
required: ['name'],
},
res: {
type: 'array',
items: {
$ref: 'https://misskey-hub.net/api/schemas/DriveFile',
},
},
}],
},
'drive/files/show': {
tags: ['drive'],
requireCredential: true,
kind: 'read:drive',
description: 'Show the properties of a drive file.',
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: '067bc436-2718-4795-b0fb-ecbe43949e31',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '25b73c73-68b1-41d0-bad1-381cfdf6579f',
},
},
defines: [{
req: {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
url: { type: 'string' },
},
anyOf: [
{ required: ['fileId'] },
{ required: ['url'] },
],
},
res: {
$ref: 'https://misskey-hub.net/api/schemas/DriveFile',
},
}],
},
'drive/files/update': {
tags: ['drive'],
requireCredential: true,
kind: 'write:drive',
description: 'Update the properties of a drive file.',
errors: {
invalidFileName: {
message: 'Invalid file name.',
code: 'INVALID_FILE_NAME',
id: '395e7156-f9f0-475e-af89-53c3c23080c2',
},
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'e7778c7e-3af9-49cd-9690-6dbc3e6c972d',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '01a53b27-82fc-445b-a0c1-b558465a8ed2',
},
noSuchFolder: {
message: 'No such folder.',
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',
},
},
defines: [{
req: {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
folderId: { type: 'string', format: 'misskey:id', nullable: true },
name: { type: 'string' },
isSensitive: { type: 'boolean' },
comment: {
oneOf: [
{ type: 'string', maxLength: 512 },
{ type: 'null' },
],
},
},
required: ['fileId'],
},
res: {
$ref: 'https://misskey-hub.net/api/schemas/DriveFile',
},
}],
},
'drive/files/upload-from-url': {
tags: ['drive'],
limit: {
duration: ms('1hour'),
max: 60,
},
description: 'Request the server to download a new drive file from the specified URL.',
requireCredential: true,
prohibitMoved: true,
kind: 'write:drive',
defines: [{
req: {
type: 'object',
properties: {
url: { type: 'string' },
folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null },
isSensitive: { type: 'boolean', default: false },
comment: { type: 'string', nullable: true, maxLength: 512, default: null },
marker: { type: 'string', nullable: true, default: null },
force: { type: 'boolean', default: false },
},
required: ['url'],
},
res: undefined,
}],
},
//#endregion //#endregion
} as const satisfies { [x: string]: IEndpointMeta; }; } as const satisfies { [x: string]: IEndpointMeta; };