2022-09-17 21:27:08 +03:00
|
|
|
import { Inject, Injectable } from '@nestjs/common';
|
2022-12-03 12:42:05 +02:00
|
|
|
import cors from '@fastify/cors';
|
|
|
|
import multipart from '@fastify/multipart';
|
|
|
|
import { ModuleRef, repl } from '@nestjs/core';
|
2022-09-20 23:33:11 +03:00
|
|
|
import type { Config } from '@/config.js';
|
|
|
|
import type { UsersRepository, InstancesRepository, AccessTokensRepository } from '@/models/index.js';
|
2022-09-17 21:27:08 +03:00
|
|
|
import { DI } from '@/di-symbols.js';
|
|
|
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
2022-12-03 12:42:05 +02:00
|
|
|
import endpoints, { IEndpoint } from './endpoints.js';
|
2022-09-17 21:27:08 +03:00
|
|
|
import { ApiCallService } from './ApiCallService.js';
|
|
|
|
import { SignupApiService } from './SignupApiService.js';
|
|
|
|
import { SigninApiService } from './SigninApiService.js';
|
|
|
|
import { GithubServerService } from './integration/GithubServerService.js';
|
|
|
|
import { DiscordServerService } from './integration/DiscordServerService.js';
|
|
|
|
import { TwitterServerService } from './integration/TwitterServerService.js';
|
2022-12-04 08:03:09 +02:00
|
|
|
import { bindThis } from '@/decorators.js';
|
2022-12-13 17:01:45 +02:00
|
|
|
import type { FastifyInstance, FastifyPluginOptions } from 'fastify';
|
2022-09-17 21:27:08 +03: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,
|
|
|
|
private signupApiServiceService: SignupApiService,
|
|
|
|
private signinApiServiceService: SigninApiService,
|
|
|
|
private githubServerService: GithubServerService,
|
|
|
|
private discordServerService: DiscordServerService,
|
|
|
|
private twitterServerService: TwitterServerService,
|
|
|
|
) {
|
2022-12-04 08:03:09 +02:00
|
|
|
//this.createServer = this.createServer.bind(this);
|
2022-09-17 21:27:08 +03:00
|
|
|
}
|
|
|
|
|
2022-12-04 08:03:09 +02:00
|
|
|
@bindThis
|
2022-12-03 12:42:05 +02:00
|
|
|
public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
|
|
|
|
fastify.register(cors, {
|
2022-09-17 21:27:08 +03:00
|
|
|
origin: '*',
|
|
|
|
});
|
|
|
|
|
2022-12-03 12:42:05 +02:00
|
|
|
fastify.register(multipart, {
|
2022-09-17 21:27:08 +03:00
|
|
|
limits: {
|
|
|
|
fileSize: this.config.maxFileSize ?? 262144000,
|
|
|
|
files: 1,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2022-12-03 12:42:05 +02:00
|
|
|
// Prevent cache
|
|
|
|
fastify.addHook('onRequest', (request, reply, done) => {
|
|
|
|
reply.header('Cache-Control', 'private, max-age=0, must-revalidate');
|
|
|
|
done();
|
|
|
|
});
|
2022-09-17 21:27:08 +03:00
|
|
|
|
|
|
|
for (const endpoint of endpoints) {
|
2022-12-03 12:42:05 +02: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 21:27:08 +03:00
|
|
|
if (endpoint.meta.requireFile) {
|
2022-12-03 12:42:05 +02: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);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.apiCallService.handleMultipartRequest(ep, request, reply);
|
|
|
|
});
|
2022-09-17 21:27:08 +03:00
|
|
|
} else {
|
2022-12-03 12:42:05 +02: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);
|
|
|
|
return;
|
2022-09-17 21:27:08 +03:00
|
|
|
}
|
2022-12-03 12:42:05 +02:00
|
|
|
|
|
|
|
this.apiCallService.handleRequest(ep, request, reply);
|
|
|
|
});
|
2022-09-17 21:27:08 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-03 12:42:05 +02:00
|
|
|
fastify.post<{
|
|
|
|
Body: {
|
|
|
|
username: string;
|
|
|
|
password: string;
|
|
|
|
host?: string;
|
|
|
|
invitationCode?: string;
|
|
|
|
emailAddress?: string;
|
|
|
|
'hcaptcha-response'?: string;
|
|
|
|
'g-recaptcha-response'?: string;
|
|
|
|
'turnstile-response'?: string;
|
|
|
|
}
|
|
|
|
}>('/signup', (request, reply) => this.signupApiServiceService.signup(request, reply));
|
|
|
|
|
|
|
|
fastify.post<{
|
|
|
|
Body: {
|
|
|
|
username: string;
|
|
|
|
password: string;
|
|
|
|
token?: string;
|
|
|
|
signature?: string;
|
|
|
|
authenticatorData?: string;
|
|
|
|
clientDataJSON?: string;
|
|
|
|
credentialId?: string;
|
|
|
|
challengeId?: string;
|
|
|
|
};
|
|
|
|
}>('/signin', (request, reply) => this.signinApiServiceService.signin(request, reply));
|
|
|
|
|
|
|
|
fastify.post<{ Body: { code: string; } }>('/signup-pending', (request, reply) => this.signupApiServiceService.signupPending(request, reply));
|
|
|
|
|
|
|
|
fastify.register(this.discordServerService.create);
|
|
|
|
fastify.register(this.githubServerService.create);
|
|
|
|
fastify.register(this.twitterServerService.create);
|
|
|
|
|
|
|
|
fastify.get('/v1/instance/peers', async (request, reply) => {
|
2022-09-17 21:27:08 +03:00
|
|
|
const instances = await this.instancesRepository.find({
|
|
|
|
select: ['host'],
|
|
|
|
});
|
|
|
|
|
2022-12-03 12:42:05 +02:00
|
|
|
return instances.map(instance => instance.host);
|
2022-09-17 21:27:08 +03:00
|
|
|
});
|
|
|
|
|
2022-12-03 12:42:05 +02:00
|
|
|
fastify.post<{ Params: { session: string; } }>('/miauth/:session/check', async (request, reply) => {
|
2022-09-17 21:27:08 +03:00
|
|
|
const token = await this.accessTokensRepository.findOneBy({
|
2022-12-03 12:42:05 +02:00
|
|
|
session: request.params.session,
|
2022-09-17 21:27:08 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
if (token && token.session != null && !token.fetched) {
|
|
|
|
this.accessTokensRepository.update(token.id, {
|
|
|
|
fetched: true,
|
|
|
|
});
|
|
|
|
|
2022-12-03 12:42:05 +02:00
|
|
|
return {
|
2022-09-17 21:27:08 +03:00
|
|
|
ok: true,
|
|
|
|
token: token.token,
|
|
|
|
user: await this.userEntityService.pack(token.userId, null, { detail: true }),
|
|
|
|
};
|
|
|
|
} else {
|
2022-12-03 12:42:05 +02:00
|
|
|
return {
|
2022-09-17 21:27:08 +03:00
|
|
|
ok: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-12-03 12:42:05 +02:00
|
|
|
done();
|
2022-09-17 21:27:08 +03:00
|
|
|
}
|
|
|
|
}
|