2022-09-17 18:27:08 +00:00
|
|
|
import { Inject, Injectable } from '@nestjs/common';
|
2022-12-03 10:42:05 +00:00
|
|
|
import cors from '@fastify/cors';
|
|
|
|
import multipart from '@fastify/multipart';
|
2022-12-17 02:02:49 +00:00
|
|
|
import fastifyCookie from '@fastify/cookie';
|
2022-12-03 10:42:05 +00:00
|
|
|
import { ModuleRef, repl } from '@nestjs/core';
|
2022-09-20 20:33:11 +00:00
|
|
|
import type { Config } from '@/config.js';
|
|
|
|
import type { UsersRepository, InstancesRepository, AccessTokensRepository } from '@/models/index.js';
|
2022-09-17 18:27:08 +00:00
|
|
|
import { DI } from '@/di-symbols.js';
|
|
|
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
2022-12-17 02:02:49 +00:00
|
|
|
import { bindThis } from '@/decorators.js';
|
2022-12-03 10:42:05 +00:00
|
|
|
import endpoints, { IEndpoint } from './endpoints.js';
|
2022-09-17 18:27:08 +00:00
|
|
|
import { ApiCallService } from './ApiCallService.js';
|
|
|
|
import { SignupApiService } from './SignupApiService.js';
|
|
|
|
import { SigninApiService } from './SigninApiService.js';
|
2022-12-13 15:01:45 +00:00
|
|
|
import type { FastifyInstance, FastifyPluginOptions } from 'fastify';
|
2022-09-17 18:27:08 +00:00
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
export class ApiServerService {
|
|
|
|
constructor(
|
|
|
|
private moduleRef: ModuleRef,
|
|
|
|
|
|
|
|
@Inject(DI.config)
|
|
|
|
private config: Config,
|
|
|
|
|
|
|
|
@Inject(DI.usersRepository)
|
|
|
|
private usersRepository: UsersRepository,
|
|
|
|
|
|
|
|
@Inject(DI.instancesRepository)
|
|
|
|
private instancesRepository: InstancesRepository,
|
|
|
|
|
|
|
|
@Inject(DI.accessTokensRepository)
|
|
|
|
private accessTokensRepository: AccessTokensRepository,
|
|
|
|
|
|
|
|
private userEntityService: UserEntityService,
|
|
|
|
private apiCallService: ApiCallService,
|
2023-01-13 08:49:05 +00:00
|
|
|
private signupApiService: SignupApiService,
|
|
|
|
private signinApiService: SigninApiService,
|
2022-09-17 18:27:08 +00:00
|
|
|
) {
|
2022-12-04 06:03:09 +00:00
|
|
|
//this.createServer = this.createServer.bind(this);
|
2022-09-17 18:27:08 +00:00
|
|
|
}
|
|
|
|
|
2022-12-04 06:03:09 +00:00
|
|
|
@bindThis
|
2022-12-03 10:42:05 +00:00
|
|
|
public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
|
|
|
|
fastify.register(cors, {
|
2022-09-17 18:27:08 +00:00
|
|
|
origin: '*',
|
|
|
|
});
|
|
|
|
|
2022-12-03 10:42:05 +00:00
|
|
|
fastify.register(multipart, {
|
2022-09-17 18:27:08 +00:00
|
|
|
limits: {
|
|
|
|
fileSize: this.config.maxFileSize ?? 262144000,
|
|
|
|
files: 1,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2022-12-17 02:02:49 +00:00
|
|
|
fastify.register(fastifyCookie, {});
|
|
|
|
|
2022-12-03 10:42:05 +00:00
|
|
|
// Prevent cache
|
|
|
|
fastify.addHook('onRequest', (request, reply, done) => {
|
|
|
|
reply.header('Cache-Control', 'private, max-age=0, must-revalidate');
|
|
|
|
done();
|
|
|
|
});
|
2022-09-17 18:27:08 +00:00
|
|
|
|
|
|
|
for (const endpoint of endpoints) {
|
2022-12-03 10:42:05 +00:00
|
|
|
const ep = {
|
|
|
|
name: endpoint.name,
|
|
|
|
meta: endpoint.meta,
|
|
|
|
params: endpoint.params,
|
|
|
|
exec: this.moduleRef.get('ep:' + endpoint.name, { strict: false }).exec,
|
|
|
|
};
|
|
|
|
|
2022-09-17 18:27:08 +00:00
|
|
|
if (endpoint.meta.requireFile) {
|
2022-12-03 10:42:05 +00:00
|
|
|
fastify.all<{
|
|
|
|
Params: { endpoint: string; },
|
|
|
|
Body: Record<string, unknown>,
|
|
|
|
Querystring: Record<string, unknown>,
|
|
|
|
}>('/' + endpoint.name, (request, reply) => {
|
|
|
|
if (request.method === 'GET' && !endpoint.meta.allowGet) {
|
|
|
|
reply.code(405);
|
2022-12-24 04:55:50 +00:00
|
|
|
reply.send();
|
2022-12-03 10:42:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.apiCallService.handleMultipartRequest(ep, request, reply);
|
|
|
|
});
|
2022-09-17 18:27:08 +00:00
|
|
|
} else {
|
2022-12-03 10:42:05 +00:00
|
|
|
fastify.all<{
|
|
|
|
Params: { endpoint: string; },
|
|
|
|
Body: Record<string, unknown>,
|
|
|
|
Querystring: Record<string, unknown>,
|
2022-12-28 00:07:41 +00:00
|
|
|
}>('/' + endpoint.name, { bodyLimit: 1024 * 32 }, (request, reply) => {
|
2022-12-03 10:42:05 +00:00
|
|
|
if (request.method === 'GET' && !endpoint.meta.allowGet) {
|
|
|
|
reply.code(405);
|
2022-12-24 04:55:50 +00:00
|
|
|
reply.send();
|
2022-12-03 10:42:05 +00:00
|
|
|
return;
|
2022-09-17 18:27:08 +00:00
|
|
|
}
|
2022-12-03 10:42:05 +00:00
|
|
|
|
|
|
|
this.apiCallService.handleRequest(ep, request, reply);
|
|
|
|
});
|
2022-09-17 18:27:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-03 10:42:05 +00:00
|
|
|
fastify.post<{
|
|
|
|
Body: {
|
|
|
|
username: string;
|
|
|
|
password: string;
|
|
|
|
host?: string;
|
|
|
|
invitationCode?: string;
|
|
|
|
emailAddress?: string;
|
|
|
|
'hcaptcha-response'?: string;
|
|
|
|
'g-recaptcha-response'?: string;
|
|
|
|
'turnstile-response'?: string;
|
|
|
|
}
|
2023-01-13 08:49:05 +00:00
|
|
|
}>('/signup', (request, reply) => this.signupApiService.signup(request, reply));
|
2022-12-03 10:42:05 +00:00
|
|
|
|
|
|
|
fastify.post<{
|
|
|
|
Body: {
|
|
|
|
username: string;
|
|
|
|
password: string;
|
|
|
|
token?: string;
|
|
|
|
signature?: string;
|
|
|
|
authenticatorData?: string;
|
|
|
|
clientDataJSON?: string;
|
|
|
|
credentialId?: string;
|
|
|
|
challengeId?: string;
|
|
|
|
};
|
2023-01-13 08:49:05 +00:00
|
|
|
}>('/signin', (request, reply) => this.signinApiService.signin(request, reply));
|
2022-12-03 10:42:05 +00:00
|
|
|
|
2023-01-13 08:49:05 +00:00
|
|
|
fastify.post<{ Body: { code: string; } }>('/signup-pending', (request, reply) => this.signupApiService.signupPending(request, reply));
|
2022-12-03 10:42:05 +00:00
|
|
|
|
|
|
|
fastify.get('/v1/instance/peers', async (request, reply) => {
|
2022-09-17 18:27:08 +00:00
|
|
|
const instances = await this.instancesRepository.find({
|
|
|
|
select: ['host'],
|
2022-12-19 00:00:13 +00:00
|
|
|
where: {
|
|
|
|
isSuspended: false,
|
|
|
|
},
|
2022-09-17 18:27:08 +00:00
|
|
|
});
|
|
|
|
|
2022-12-03 10:42:05 +00:00
|
|
|
return instances.map(instance => instance.host);
|
2022-09-17 18:27:08 +00:00
|
|
|
});
|
|
|
|
|
2022-12-03 10:42:05 +00:00
|
|
|
fastify.post<{ Params: { session: string; } }>('/miauth/:session/check', async (request, reply) => {
|
2022-09-17 18:27:08 +00:00
|
|
|
const token = await this.accessTokensRepository.findOneBy({
|
2022-12-03 10:42:05 +00:00
|
|
|
session: request.params.session,
|
2022-09-17 18:27:08 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
if (token && token.session != null && !token.fetched) {
|
|
|
|
this.accessTokensRepository.update(token.id, {
|
|
|
|
fetched: true,
|
|
|
|
});
|
|
|
|
|
2022-12-03 10:42:05 +00:00
|
|
|
return {
|
2022-09-17 18:27:08 +00:00
|
|
|
ok: true,
|
|
|
|
token: token.token,
|
|
|
|
user: await this.userEntityService.pack(token.userId, null, { detail: true }),
|
|
|
|
};
|
|
|
|
} else {
|
2022-12-03 10:42:05 +00:00
|
|
|
return {
|
2022-09-17 18:27:08 +00:00
|
|
|
ok: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-12-03 10:42:05 +00:00
|
|
|
done();
|
2022-09-17 18:27:08 +00:00
|
|
|
}
|
|
|
|
}
|