Merge remote-tracking branch 'misskey-dev/develop' into io

This commit is contained in:
まっちゃとーにゅ
2024-02-22 06:50:17 +09:00
252 changed files with 4312 additions and 3337 deletions

View File

@@ -27,6 +27,7 @@ import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js';
import { isMimeImage } from '@/misc/is-mime-image.js';
import { correctFilename } from '@/misc/correct-filename.js';
import { handleRequestRedirectToOmitSearch } from '@/misc/fastify-hook-handlers.js';
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify';
const _filename = fileURLToPath(import.meta.url);
@@ -67,20 +68,23 @@ export class FileServerService {
done();
});
fastify.get('/files/app-default.jpg', (request, reply) => {
const file = fs.createReadStream(`${_dirname}/assets/dummy.png`);
reply.header('Content-Type', 'image/jpeg');
reply.header('Cache-Control', 'max-age=31536000, immutable');
return reply.send(file);
});
fastify.register((fastify, options, done) => {
fastify.addHook('onRequest', handleRequestRedirectToOmitSearch);
fastify.get('/files/app-default.jpg', (request, reply) => {
const file = fs.createReadStream(`${_dirname}/assets/dummy.png`);
reply.header('Content-Type', 'image/jpeg');
reply.header('Cache-Control', 'max-age=31536000, immutable');
return reply.send(file);
});
fastify.get<{ Params: { key: string; } }>('/files/:key', async (request, reply) => {
return await this.sendDriveFile(request, reply)
.catch(err => this.errorHandler(request, reply, err));
});
fastify.get<{ Params: { key: string; } }>('/files/:key/*', async (request, reply) => {
return await this.sendDriveFile(request, reply)
.catch(err => this.errorHandler(request, reply, err));
fastify.get<{ Params: { key: string; } }>('/files/:key', async (request, reply) => {
return await this.sendDriveFile(request, reply)
.catch(err => this.errorHandler(request, reply, err));
});
fastify.get<{ Params: { key: string; } }>('/files/:key/*', async (request, reply) => {
return await reply.redirect(301, `${this.config.url}/files/${request.params.key}`);
});
done();
});
fastify.get<{

View File

@@ -37,12 +37,12 @@ export class NodeinfoServerService {
@bindThis
public getLinks() {
return [{
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.1',
href: this.config.url + nodeinfo2_1path,
}, {
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0',
href: this.config.url + nodeinfo2_0path,
}];
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.1',
href: this.config.url + nodeinfo2_1path
}, {
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0',
href: this.config.url + nodeinfo2_0path,
}];
}
@bindThis
@@ -117,6 +117,8 @@ export class NodeinfoServerService {
emailRequiredForSignup: meta.emailRequiredForSignup,
enableHcaptcha: meta.enableHcaptcha,
enableRecaptcha: meta.enableRecaptcha,
enableMcaptcha: meta.enableMcaptcha,
enableTurnstile: meta.enableTurnstile,
maxNoteTextLength: MAX_NOTE_TEXT_LENGTH,
enableEmail: meta.enableEmail,
enableServiceWorker: meta.enableServiceWorker,

View File

@@ -15,9 +15,6 @@ export const meta = {
requireCredential: true,
requireAdmin: true,
kind: 'write:admin:delete-account',
res: {
},
} as const;
export const paramDef = {

View File

@@ -84,6 +84,24 @@ export const meta = {
properties: {
type: 'object',
optional: false, nullable: false,
properties: {
width: {
type: 'number',
optional: true, nullable: false,
},
height: {
type: 'number',
optional: true, nullable: false,
},
orientation: {
type: 'number',
optional: true, nullable: false,
},
avgColor: {
type: 'string',
optional: true, nullable: false,
},
},
},
storedInternal: {
type: 'boolean',

View File

@@ -18,6 +18,18 @@ export const meta = {
res: {
type: 'object',
optional: false, nullable: false,
additionalProperties: {
type: 'object',
properties: {
count: {
type: 'number',
},
size: {
type: 'number',
},
},
required: ['count', 'size'],
},
example: {
migrations: {
count: 66,

View File

@@ -454,7 +454,7 @@ export const meta = {
},
repositoryUrl: {
type: 'string',
optional: false, nullable: false,
optional: false, nullable: true,
},
summalyProxy: {
type: 'string',

View File

@@ -17,7 +17,7 @@ export const meta = {
tags: ['admin', 'role', 'users'],
requireCredential: false,
requireAdmin: true,
requireModerator: true,
kind: 'read:admin:roles',
errors: {

View File

@@ -10,6 +10,7 @@ import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js';
import { RoleEntityService } from '@/core/entities/RoleEntityService.js';
import { IdService } from '@/core/IdService.js';
import { notificationRecieveConfig } from '@/models/json-schema/user.js';
export const meta = {
tags: ['admin'],
@@ -21,6 +22,157 @@ export const meta = {
res: {
type: 'object',
nullable: false, optional: false,
properties: {
email: {
type: 'string',
optional: false, nullable: true,
},
emailVerified: {
type: 'boolean',
optional: false, nullable: false,
},
autoAcceptFollowed: {
type: 'boolean',
optional: false, nullable: false,
},
noCrawle: {
type: 'boolean',
optional: false, nullable: false,
},
preventAiLearning: {
type: 'boolean',
optional: false, nullable: false,
},
alwaysMarkNsfw: {
type: 'boolean',
optional: false, nullable: false,
},
autoSensitive: {
type: 'boolean',
optional: false, nullable: false,
},
carefulBot: {
type: 'boolean',
optional: false, nullable: false,
},
injectFeaturedNote: {
type: 'boolean',
optional: false, nullable: false,
},
receiveAnnouncementEmail: {
type: 'boolean',
optional: false, nullable: false,
},
mutedWords: {
type: 'array',
optional: false, nullable: false,
items: {
anyOf: [
{
type: 'string',
},
{
type: 'array',
items: {
type: 'string',
},
},
],
},
},
mutedInstances: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'string',
},
},
notificationRecieveConfig: {
type: 'object',
optional: false, nullable: false,
properties: {
note: { optional: true, ...notificationRecieveConfig },
follow: { optional: true, ...notificationRecieveConfig },
mention: { optional: true, ...notificationRecieveConfig },
reply: { optional: true, ...notificationRecieveConfig },
renote: { optional: true, ...notificationRecieveConfig },
quote: { optional: true, ...notificationRecieveConfig },
reaction: { optional: true, ...notificationRecieveConfig },
pollEnded: { optional: true, ...notificationRecieveConfig },
receiveFollowRequest: { optional: true, ...notificationRecieveConfig },
followRequestAccepted: { optional: true, ...notificationRecieveConfig },
roleAssigned: { optional: true, ...notificationRecieveConfig },
achievementEarned: { optional: true, ...notificationRecieveConfig },
app: { optional: true, ...notificationRecieveConfig },
test: { optional: true, ...notificationRecieveConfig },
},
},
isModerator: {
type: 'boolean',
optional: false, nullable: false,
},
isSilenced: {
type: 'boolean',
optional: false, nullable: false,
},
isSuspended: {
type: 'boolean',
optional: false, nullable: false,
},
isHibernated: {
type: 'boolean',
optional: false, nullable: false,
},
lastActiveDate: {
type: 'string',
optional: false, nullable: true,
},
moderationNote: {
type: 'string',
optional: false, nullable: false,
},
signins: {
type: 'array',
optional: false, nullable: false,
items: {
ref: 'Signin',
},
},
policies: {
type: 'object',
optional: false, nullable: false,
ref: 'RolePolicies',
},
roles: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'object',
ref: 'Role',
},
},
roleAssigns: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'object',
properties: {
createdAt: {
type: 'string',
optional: false, nullable: false,
},
expiresAt: {
type: 'string',
optional: false, nullable: true,
},
roleId: {
type: 'string',
optional: false, nullable: false,
},
},
},
},
},
},
} as const;
@@ -92,7 +244,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
isLimited: isLimited,
isSuspended: user.isSuspended,
isHibernated: user.isHibernated,
lastActiveDate: user.lastActiveDate,
lastActiveDate: user.lastActiveDate ? user.lastActiveDate.toISOString() : null,
moderationNote: profile.moderationNote ?? '',
signins,
policies: await this.roleService.getUserPolicies(user.id),

View File

@@ -437,7 +437,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
if (ps.repositoryUrl !== undefined) {
set.repositoryUrl = ps.repositoryUrl ?? 'https://github.com/misskey-dev/misskey';
set.repositoryUrl = URL.canParse(ps.repositoryUrl!) ? ps.repositoryUrl : null;
}
if (ps.feedbackUrl !== undefined) {

View File

@@ -24,9 +24,19 @@ export const meta = {
type: 'object',
optional: false, nullable: false,
properties: {
id: { type: 'string', format: 'misskey:id' },
score: { type: 'integer' },
user: { ref: 'UserLite' },
id: {
type: 'string', format: 'misskey:id',
optional: false, nullable: false,
},
score: {
type: 'integer',
optional: false, nullable: false,
},
user: {
type: 'object',
optional: true, nullable: false,
ref: 'UserLite',
},
},
},
},

View File

@@ -29,9 +29,6 @@ export const meta = {
id: 'eb627bc7-574b-4a52-a860-3c3eae772b88',
},
},
res: {
},
} as const;
export const paramDef = {
@@ -39,7 +36,15 @@ export const paramDef = {
properties: {
score: { type: 'integer', minimum: 0 },
seed: { type: 'string', minLength: 1, maxLength: 1024 },
logs: { type: 'array' },
logs: {
type: 'array',
items: {
type: 'array',
items: {
type: 'number',
},
},
},
gameMode: { type: 'string' },
gameVersion: { type: 'integer' },
},

View File

@@ -15,6 +15,19 @@ export const meta = {
requireCredential: true,
secure: true,
res: {
type: 'object',
properties: {
backupCodes: {
type: 'array',
optional: false,
items: {
type: 'string',
},
},
},
},
} as const;
export const paramDef = {

View File

@@ -53,7 +53,7 @@ export const meta = {
properties: {
id: {
type: 'string',
nullable: true,
optional: true,
},
},
},

View File

@@ -21,21 +21,26 @@ export const meta = {
properties: {
id: {
type: 'string',
optional: false,
format: 'misskey:id',
},
name: {
type: 'string',
optional: true,
},
createdAt: {
type: 'string',
optional: false,
format: 'date-time',
},
lastUsedAt: {
type: 'string',
optional: true,
format: 'date-time',
},
permission: {
type: 'array',
optional: false,
uniqueItems: true,
items: {
type: 'string',

View File

@@ -23,16 +23,19 @@ export const meta = {
id: {
type: 'string',
format: 'misskey:id',
optional: false,
},
name: {
type: 'string',
optional: false,
},
callbackUrl: {
type: 'string',
nullable: true,
optional: false, nullable: true,
},
permission: {
type: 'array',
optional: false,
uniqueItems: true,
items: {
type: 'string',
@@ -40,6 +43,7 @@ export const meta = {
},
isAuthorized: {
type: 'boolean',
optional: true,
},
},
},

View File

@@ -22,6 +22,15 @@ export const meta = {
res: {
type: 'object',
properties: {
updatedAt: {
type: 'string',
optional: false,
},
value: {
optional: false,
},
},
},
} as const;
@@ -50,7 +59,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
return {
updatedAt: item.updatedAt,
updatedAt: item.updatedAt.toISOString(),
value: item.value,
};
});

View File

@@ -13,6 +13,9 @@ export const meta = {
res: {
type: 'object',
additionalProperties: {
type: 'string',
},
},
} as const;

View File

@@ -10,6 +10,13 @@ import { RegistryApiService } from '@/core/RegistryApiService.js';
export const meta = {
requireCredential: true,
kind: 'read:account',
res: {
type: 'array',
items: {
type: 'string',
},
},
} as const;
export const paramDef = {

View File

@@ -32,6 +32,7 @@ import { HttpRequestService } from '@/core/HttpRequestService.js';
import type { Config } from '@/config.js';
import { safeForSql } from '@/misc/safe-for-sql.js';
import { AvatarDecorationService } from '@/core/AvatarDecorationService.js';
import { notificationRecieveConfig } from '@/models/json-schema/user.js';
import { ApiLoggerService } from '../../ApiLoggerService.js';
import { ApiError } from '../../error.js';
@@ -183,7 +184,26 @@ export const paramDef = {
mutedInstances: { type: 'array', items: {
type: 'string',
} },
notificationRecieveConfig: { type: 'object' },
notificationRecieveConfig: {
type: 'object',
nullable: false,
properties: {
note: notificationRecieveConfig,
follow: notificationRecieveConfig,
mention: notificationRecieveConfig,
reply: notificationRecieveConfig,
renote: notificationRecieveConfig,
quote: notificationRecieveConfig,
reaction: notificationRecieveConfig,
pollEnded: notificationRecieveConfig,
receiveFollowRequest: notificationRecieveConfig,
followRequestAccepted: notificationRecieveConfig,
roleAssigned: notificationRecieveConfig,
achievementEarned: notificationRecieveConfig,
app: notificationRecieveConfig,
test: notificationRecieveConfig,
},
},
emailNotificationTypes: { type: 'array', items: {
type: 'string',
} },

View File

@@ -109,7 +109,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
url: webhook.url,
secret: webhook.secret,
active: webhook.active,
latestSentAt: webhook.latestSentAt?.toISOString(),
latestSentAt: webhook.latestSentAt ? webhook.latestSentAt.toISOString() : null,
latestStatus: webhook.latestStatus,
};
});

View File

@@ -73,7 +73,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
url: webhook.url,
secret: webhook.secret,
active: webhook.active,
latestSentAt: webhook.latestSentAt?.toISOString(),
latestSentAt: webhook.latestSentAt ? webhook.latestSentAt.toISOString() : null,
latestStatus: webhook.latestStatus,
}
));

View File

@@ -85,7 +85,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
url: webhook.url,
secret: webhook.secret,
active: webhook.active,
latestSentAt: webhook.latestSentAt?.toISOString(),
latestSentAt: webhook.latestSentAt ? webhook.latestSentAt.toISOString() : null,
latestStatus: webhook.latestStatus,
};
});

View File

@@ -69,12 +69,12 @@ export const meta = {
},
repositoryUrl: {
type: 'string',
optional: false, nullable: false,
optional: false, nullable: true,
default: 'https://github.com/misskey-dev/misskey',
},
feedbackUrl: {
type: 'string',
optional: false, nullable: false,
optional: false, nullable: true,
default: 'https://github.com/misskey-dev/misskey/issues/new',
},
defaultDarkTheme: {

View File

@@ -14,9 +14,6 @@ export const meta = {
errors: {
},
res: {
},
} as const;
export const paramDef = {

View File

@@ -30,6 +30,9 @@ export const meta = {
},
res: {
type: 'object',
optional: true,
ref: 'ReversiGameDetailed',
},
} as const;

View File

@@ -19,20 +19,24 @@ export const meta = {
id: {
type: 'string',
format: 'misskey:id',
optional: true, nullable: false,
},
required: {
type: 'boolean',
optional: false, nullable: false,
},
string: {
type: 'string',
optional: true, nullable: false,
},
default: {
type: 'string',
optional: true, nullable: false,
},
nullableDefault: {
type: 'string',
default: 'hello',
nullable: true,
optional: true, nullable: true,
},
},
},

View File

@@ -34,6 +34,7 @@ import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, MiMeta, NotesRepository, PagesRepository, ReversiGamesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js';
import type Logger from '@/logger.js';
import { deepClone } from '@/misc/clone.js';
import { handleRequestRedirectToOmitSearch } from '@/misc/fastify-hook-handlers.js';
import { bindThis } from '@/decorators.js';
import { FlashEntityService } from '@/core/entities/FlashEntityService.js';
import { RoleService } from '@/core/RoleService.js';
@@ -195,7 +196,7 @@ export class ClientServerService {
// Authenticate
fastify.addHook('onRequest', async (request, reply) => {
// %71ueueとかでリクエストされたら困るため
const url = decodeURI(request.routeOptions.url);
const url = decodeURI(request.routeOptions.url ?? '');
if (url === bullBoardPath || url.startsWith(bullBoardPath + '/')) {
const token = request.cookies.token;
if (token == null) {
@@ -266,11 +267,16 @@ export class ClientServerService {
//#region vite assets
if (this.config.clientManifestExists) {
fastify.register(fastifyStatic, {
root: viteOut,
prefix: '/vite/',
maxAge: ms('30 days'),
decorateReply: false,
fastify.register((fastify, options, done) => {
fastify.register(fastifyStatic, {
root: viteOut,
prefix: '/vite/',
maxAge: ms('30 days'),
immutable: true,
decorateReply: false,
});
fastify.addHook('onRequest', handleRequestRedirectToOmitSearch);
done();
});
} else {
const port = (process.env.VITE_PORT ?? '5173');