181 lines
4.7 KiB
TypeScript
181 lines
4.7 KiB
TypeScript
import Fastify, { FastifyInstance, FastifyListenOptions } from "fastify";
|
|
import fastifyMultipart from "@fastify/multipart";
|
|
import cors from '@fastify/cors';
|
|
|
|
import { UserDB } from "./UserDB";
|
|
import { RequestHandler } from "./RequestHandler";
|
|
import { EmailService as EmailService } from "./email/EmailService";
|
|
import { TokenDB } from "./TokenDB";
|
|
import { UserManagementServerSettings } from "./UserManagementServerSettings";
|
|
import { RJLog } from "../log/RJLog";
|
|
import { Session } from "./Session";
|
|
import { Role } from "./permissions/Role";
|
|
import { RolesData } from "./permissions/RolesData";
|
|
import { Files } from "../files/Files";
|
|
import { LocationService } from "./location/LocationService";
|
|
import { RequestRequirement } from "./requirements/RequestRequirement";
|
|
import { NotTooManyRequests } from "./requirements/security/NotTooManyRequests";
|
|
|
|
export class UserManagementServer
|
|
{
|
|
_app:FastifyInstance;
|
|
get app(){ return this._app; }
|
|
|
|
_userDB:UserDB;
|
|
get userDB(){ return this._userDB; }
|
|
|
|
_tokenDB:TokenDB;
|
|
get tokenDB(){ return this._tokenDB;}
|
|
|
|
_emailService:EmailService;
|
|
get email(){ return this._emailService; }
|
|
|
|
_locationService:LocationService;
|
|
get location(){ return this._locationService; }
|
|
|
|
_sessions:Map<string,Session> = new Map<string,Session>();
|
|
_roles = new Map<string,Role>();
|
|
|
|
_handlers:RequestHandler[] = [];
|
|
|
|
_settings:UserManagementServerSettings;
|
|
_globalRequirements:RequestRequirement[] = [];
|
|
get globalRequirements(){ return this._globalRequirements; }
|
|
|
|
|
|
async initialize( settings:UserManagementServerSettings, mailService:EmailService, handlers:RequestHandler[], globalRequirements:RequestRequirement[] = null ):Promise<void>
|
|
{
|
|
this._settings = settings;
|
|
|
|
UserManagementServerSettings.makeAllPathsAbsolute( settings );
|
|
|
|
await this._initializeApp();
|
|
await this._addGlobalRequirements( globalRequirements || UserManagementServer.DefaultGlobalRequirements() );
|
|
await this._addServices( mailService );
|
|
await this._addHandlers( handlers );
|
|
|
|
await this._startServer();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
static DefaultGlobalRequirements():RequestRequirement[]
|
|
{
|
|
let globalDefaults:RequestRequirement[] =
|
|
[
|
|
new NotTooManyRequests()
|
|
];
|
|
|
|
return globalDefaults;
|
|
}
|
|
|
|
async _addGlobalRequirements( globalRequirements:RequestRequirement[] ):Promise<void>
|
|
{
|
|
this._globalRequirements = globalRequirements;
|
|
|
|
for ( let gr of this._globalRequirements )
|
|
{
|
|
await gr.initializeGlobal( this );
|
|
}
|
|
|
|
return Promise.resolve();
|
|
}
|
|
|
|
async sendEmail( to:string, title:string, message:string ):Promise<void>
|
|
{
|
|
return this.email.send( this._settings.emailFrom, to, title, message );
|
|
}
|
|
|
|
async _initializeApp():Promise<void>
|
|
{
|
|
|
|
this._app = Fastify();
|
|
this._app.register( fastifyMultipart );
|
|
|
|
for ( let corsURL of this._settings.corsURLs )
|
|
{
|
|
RJLog.log( "Adding cors:", corsURL );
|
|
|
|
await this._app.register( cors,
|
|
{
|
|
origin: corsURL,
|
|
credentials: true,
|
|
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']
|
|
}
|
|
);
|
|
}
|
|
|
|
return Promise.resolve();
|
|
}
|
|
|
|
async _addServices( mailService:EmailService ):Promise<void>
|
|
{
|
|
this._userDB = await UserDB.load( this, this._settings.userDBPath );
|
|
|
|
RJLog.log( "Loading roles:", this._settings.rolesPath );
|
|
let rolesData = await Files.loadJSON<RolesData>( this._settings.rolesPath );
|
|
this._roles = new Map<string,Role>();
|
|
rolesData.roles.forEach( r => this._roles.set( r.id, r ) );
|
|
|
|
this._tokenDB = new TokenDB( this );
|
|
this._emailService = mailService;
|
|
|
|
this._locationService = await LocationService.create(
|
|
this._settings.geoLocationPath,
|
|
this._settings.geoAccountID,
|
|
this._settings.geoLicenseKey
|
|
);
|
|
|
|
let ipToCheck = "2a02:3100:25e5:2500:65d7:61b7:33f7:9d7f";
|
|
let location = await this._locationService.getLocation( ipToCheck );
|
|
|
|
RJLog.log( "IP", ipToCheck, "Location:", location );
|
|
|
|
return Promise.resolve();
|
|
}
|
|
|
|
async _addHandlers( handlers:RequestHandler[] ):Promise<void>
|
|
{
|
|
|
|
|
|
for ( let handler of handlers )
|
|
{
|
|
await handler.initialize( this );
|
|
this._handlers.push( handler );
|
|
}
|
|
|
|
return Promise.resolve();
|
|
}
|
|
|
|
async _startServer()
|
|
{
|
|
let listenOptions:FastifyListenOptions =
|
|
{
|
|
port: this._settings.port
|
|
}
|
|
|
|
if ( ! this._settings.isDebugMode )
|
|
{
|
|
listenOptions.host = "0.0.0.0";
|
|
}
|
|
|
|
this.app.listen(
|
|
|
|
listenOptions,
|
|
|
|
( error, address ) =>
|
|
{
|
|
if ( error )
|
|
{
|
|
RJLog.error( error );
|
|
throw error;
|
|
}
|
|
|
|
RJLog.log( `Server running on ${address}` );
|
|
}
|
|
|
|
);
|
|
}
|
|
|
|
} |