summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-03-03 15:35:40 +0900
committerGitHub <noreply@github.com>2023-03-03 15:35:40 +0900
commit5bd68aa3e0ce65a9183e193ff113b2486021f679 (patch)
tree7cce90cfd87cbdfc932226273a6a89aa7871b33e /packages/backend/src/server/api
parentMerge pull request #10112 from misskey-dev/develop (diff)
parentfix CHANGELOG.md (diff)
downloadmisskey-5bd68aa3e0ce65a9183e193ff113b2486021f679.tar.gz
misskey-5bd68aa3e0ce65a9183e193ff113b2486021f679.tar.bz2
misskey-5bd68aa3e0ce65a9183e193ff113b2486021f679.zip
Merge pull request #10177 from misskey-dev/develop
Release: 13.9.0
Diffstat (limited to 'packages/backend/src/server/api')
-rw-r--r--packages/backend/src/server/api/ApiCallService.ts5
-rw-r--r--packages/backend/src/server/api/ApiServerService.ts32
-rw-r--r--packages/backend/src/server/api/endpoints.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/assign.ts29
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/unassign.ts22
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/users.ts7
-rw-r--r--packages/backend/src/server/api/endpoints/channels/timeline.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/i/update-email.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/roles/users.ts5
-rw-r--r--packages/backend/src/server/api/stream/types.ts9
10 files changed, 71 insertions, 52 deletions
diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts
index 6d8540dd4f..f84a3aa59b 100644
--- a/packages/backend/src/server/api/ApiCallService.ts
+++ b/packages/backend/src/server/api/ApiCallService.ts
@@ -100,9 +100,12 @@ export class ApiCallService implements OnApplicationShutdown {
request: FastifyRequest<{ Body: Record<string, unknown>, Querystring: Record<string, unknown> }>,
reply: FastifyReply,
) {
- const multipartData = await request.file();
+ const multipartData = await request.file().catch(() => {
+ /* Fastify throws if the remote didn't send multipart data. Return 400 below. */
+ });
if (multipartData == null) {
reply.code(400);
+ reply.send();
return;
}
diff --git a/packages/backend/src/server/api/ApiServerService.ts b/packages/backend/src/server/api/ApiServerService.ts
index 2b99da01b6..115d60986c 100644
--- a/packages/backend/src/server/api/ApiServerService.ts
+++ b/packages/backend/src/server/api/ApiServerService.ts
@@ -73,28 +73,32 @@ export class ApiServerService {
Params: { endpoint: string; },
Body: Record<string, unknown>,
Querystring: Record<string, unknown>,
- }>('/' + endpoint.name, (request, reply) => {
+ }>('/' + endpoint.name, async (request, reply) => {
if (request.method === 'GET' && !endpoint.meta.allowGet) {
reply.code(405);
reply.send();
return;
}
-
- this.apiCallService.handleMultipartRequest(ep, request, reply);
+
+ // Await so that any error can automatically be translated to HTTP 500
+ await this.apiCallService.handleMultipartRequest(ep, request, reply);
+ return reply;
});
} else {
fastify.all<{
Params: { endpoint: string; },
Body: Record<string, unknown>,
Querystring: Record<string, unknown>,
- }>('/' + endpoint.name, { bodyLimit: 1024 * 32 }, (request, reply) => {
+ }>('/' + endpoint.name, { bodyLimit: 1024 * 32 }, async (request, reply) => {
if (request.method === 'GET' && !endpoint.meta.allowGet) {
reply.code(405);
reply.send();
return;
}
-
- this.apiCallService.handleRequest(ep, request, reply);
+
+ // Await so that any error can automatically be translated to HTTP 500
+ await this.apiCallService.handleRequest(ep, request, reply);
+ return reply;
});
}
}
@@ -160,6 +164,22 @@ export class ApiServerService {
}
});
+ // Make sure any unknown path under /api returns HTTP 404 Not Found,
+ // because otherwise ClientServerService will return the base client HTML
+ // page with HTTP 200.
+ fastify.get('*', (request, reply) => {
+ reply.code(404);
+ // Mock ApiCallService.send's error handling
+ reply.send({
+ error: {
+ message: 'Unknown API endpoint.',
+ code: 'UNKNOWN_API_ENDPOINT',
+ id: '2ca3b769-540a-4f08-9dd5-b5a825b6d0f1',
+ kind: 'client',
+ },
+ });
+ });
+
done();
}
}
diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts
index 4d5ed9fb62..4f521148e0 100644
--- a/packages/backend/src/server/api/endpoints.ts
+++ b/packages/backend/src/server/api/endpoints.ts
@@ -741,8 +741,8 @@ export interface IEndpoint {
const endpoints: IEndpoint[] = (eps as [string, any]).map(([name, ep]) => {
return {
name: name,
- meta: ep.meta ?? {},
- params: ep.paramDef,
+ get meta() { return ep.meta ?? {}; },
+ get params() { return ep.paramDef; },
};
});
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/assign.ts b/packages/backend/src/server/api/endpoints/admin/roles/assign.ts
index 7bfb2f6625..b80aaba122 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/assign.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/assign.ts
@@ -1,10 +1,8 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js';
+import type { RolesRepository, UsersRepository } from '@/models/index.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '@/server/api/error.js';
-import { IdService } from '@/core/IdService.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
import { RoleService } from '@/core/RoleService.js';
export const meta = {
@@ -39,6 +37,10 @@ export const paramDef = {
properties: {
roleId: { type: 'string', format: 'misskey:id' },
userId: { type: 'string', format: 'misskey:id' },
+ expiresAt: {
+ type: 'integer',
+ nullable: true,
+ },
},
required: [
'roleId',
@@ -56,12 +58,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
@Inject(DI.rolesRepository)
private rolesRepository: RolesRepository,
- @Inject(DI.roleAssignmentsRepository)
- private roleAssignmentsRepository: RoleAssignmentsRepository,
-
- private globalEventService: GlobalEventService,
private roleService: RoleService,
- private idService: IdService,
) {
super(meta, paramDef, async (ps, me) => {
const role = await this.rolesRepository.findOneBy({ id: ps.roleId });
@@ -78,19 +75,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new ApiError(meta.errors.noSuchUser);
}
- const date = new Date();
- const created = await this.roleAssignmentsRepository.insert({
- id: this.idService.genId(),
- createdAt: date,
- roleId: role.id,
- userId: user.id,
- }).then(x => this.roleAssignmentsRepository.findOneByOrFail(x.identifiers[0]));
+ if (ps.expiresAt && ps.expiresAt <= Date.now()) {
+ return;
+ }
- this.rolesRepository.update(ps.roleId, {
- lastUsedAt: new Date(),
- });
-
- this.globalEventService.publishInternalEvent('userRoleAssigned', created);
+ await this.roleService.assign(user.id, role.id, ps.expiresAt ? new Date(ps.expiresAt) : null);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts b/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts
index 141cc5ee89..45c4f76943 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts
@@ -1,10 +1,8 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js';
+import type { RolesRepository, UsersRepository } from '@/models/index.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '@/server/api/error.js';
-import { IdService } from '@/core/IdService.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
import { RoleService } from '@/core/RoleService.js';
export const meta = {
@@ -62,12 +60,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
@Inject(DI.rolesRepository)
private rolesRepository: RolesRepository,
- @Inject(DI.roleAssignmentsRepository)
- private roleAssignmentsRepository: RoleAssignmentsRepository,
-
- private globalEventService: GlobalEventService,
private roleService: RoleService,
- private idService: IdService,
) {
super(meta, paramDef, async (ps, me) => {
const role = await this.rolesRepository.findOneBy({ id: ps.roleId });
@@ -84,18 +77,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new ApiError(meta.errors.noSuchUser);
}
- const roleAssignment = await this.roleAssignmentsRepository.findOneBy({ userId: user.id, roleId: role.id });
- if (roleAssignment == null) {
- throw new ApiError(meta.errors.notAssigned);
- }
-
- await this.roleAssignmentsRepository.delete(roleAssignment.id);
-
- this.rolesRepository.update(ps.roleId, {
- lastUsedAt: new Date(),
- });
-
- this.globalEventService.publishInternalEvent('userRoleUnassigned', roleAssignment);
+ await this.roleService.unassign(user.id, role.id);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/users.ts b/packages/backend/src/server/api/endpoints/admin/roles/users.ts
index bb016a8425..35edca5460 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/users.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/users.ts
@@ -1,4 +1,5 @@
import { Inject, Injectable } from '@nestjs/common';
+import { Brackets } from 'typeorm';
import type { RoleAssignmentsRepository, RolesRepository } from '@/models/index.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { QueryService } from '@/core/QueryService.js';
@@ -56,6 +57,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const query = this.queryService.makePaginationQuery(this.roleAssignmentsRepository.createQueryBuilder('assign'), ps.sinceId, ps.untilId)
.andWhere('assign.roleId = :roleId', { roleId: role.id })
+ .andWhere(new Brackets(qb => { qb
+ .where('assign.expiresAt IS NULL')
+ .orWhere('assign.expiresAt > :now', { now: new Date() });
+ }))
.innerJoinAndSelect('assign.user', 'user');
const assigns = await query
@@ -64,7 +69,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
return await Promise.all(assigns.map(async assign => ({
id: assign.id,
+ createdAt: assign.createdAt,
user: await this.userEntityService.pack(assign.user!, me, { detail: true }),
+ expiresAt: assign.expiresAt,
})));
});
}
diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts
index 58f8835279..cdaa400137 100644
--- a/packages/backend/src/server/api/endpoints/channels/timeline.ts
+++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts
@@ -82,6 +82,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner')
.leftJoinAndSelect('note.channel', 'channel');
+
+ if (me) {
+ this.queryService.generateMutedUserQuery(query, me);
+ this.queryService.generateMutedNoteQuery(query, me);
+ this.queryService.generateBlockedUserQuery(query, me);
+ }
//#endregion
const timeline = await query.take(ps.limit).getMany();
diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts
index b656c5c51d..4f543a6472 100644
--- a/packages/backend/src/server/api/endpoints/i/update-email.ts
+++ b/packages/backend/src/server/api/endpoints/i/update-email.ts
@@ -73,8 +73,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
}
if (ps.email != null) {
- const available = await this.emailService.validateEmailForAccount(ps.email);
- if (!available) {
+ const res = await this.emailService.validateEmailForAccount(ps.email);
+ if (!res.available) {
throw new ApiError(meta.errors.unavailable);
}
}
diff --git a/packages/backend/src/server/api/endpoints/roles/users.ts b/packages/backend/src/server/api/endpoints/roles/users.ts
index 6e221b6c67..607dc24206 100644
--- a/packages/backend/src/server/api/endpoints/roles/users.ts
+++ b/packages/backend/src/server/api/endpoints/roles/users.ts
@@ -1,4 +1,5 @@
import { Inject, Injectable } from '@nestjs/common';
+import { Brackets } from 'typeorm';
import type { RoleAssignmentsRepository, RolesRepository } from '@/models/index.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { QueryService } from '@/core/QueryService.js';
@@ -56,6 +57,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const query = this.queryService.makePaginationQuery(this.roleAssignmentsRepository.createQueryBuilder('assign'), ps.sinceId, ps.untilId)
.andWhere('assign.roleId = :roleId', { roleId: role.id })
+ .andWhere(new Brackets(qb => { qb
+ .where('assign.expiresAt IS NULL')
+ .orWhere('assign.expiresAt > :now', { now: new Date() });
+ }))
.innerJoinAndSelect('assign.user', 'user');
const assigns = await query
diff --git a/packages/backend/src/server/api/stream/types.ts b/packages/backend/src/server/api/stream/types.ts
index 9287952cb6..c450773055 100644
--- a/packages/backend/src/server/api/stream/types.ts
+++ b/packages/backend/src/server/api/stream/types.ts
@@ -178,7 +178,14 @@ type EventUnionFromDictionary<
// redis通すとDateのインスタンスはstringに変換されるので
type Serialized<T> = {
- [K in keyof T]: T[K] extends Date ? string : T[K] extends Record<string, any> ? Serialized<T[K]> : T[K];
+ [K in keyof T]:
+ T[K] extends Date
+ ? string
+ : T[K] extends (Date | null)
+ ? (string | null)
+ : T[K] extends Record<string, any>
+ ? Serialized<T[K]>
+ : T[K];
};
type SerializedAll<T> = {