library-ts/node/users/UserManagementServer.ts

196 lines
4.9 KiB
TypeScript
Raw Normal View History

2025-11-11 10:33:59 +00:00
import Fastify, { FastifyHttpsOptions, FastifyInstance, FastifyListenOptions } from "fastify";
2025-11-10 17:41:48 +00:00
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>
{
2025-11-11 10:33:59 +00:00
if ( this._settings.isDebugMode )
{
this._app = Fastify();
}
else
{
this._app = Fastify(
{
https:
{
key:this._settings.httpsKeyPath,
cert:this._settings.httpsCertPath
}
}
);
}
2025-11-10 17:41:48 +00:00
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 );
2025-11-10 19:27:50 +00:00
RJLog.log( "Loading roles:", this._settings.rolesPath );
2025-11-10 17:41:48 +00:00
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()
{
2025-11-11 09:35:13 +00:00
let listenOptions:FastifyListenOptions =
{
port: this._settings.port
}
if ( ! this._settings.isDebugMode )
{
listenOptions.host = "0.0.0.0";
}
2025-11-10 17:41:48 +00:00
this.app.listen(
2025-11-11 09:35:13 +00:00
listenOptions,
2025-11-10 17:41:48 +00:00
( error, address ) =>
{
if ( error )
{
RJLog.error( error );
throw error;
}
RJLog.log( `Server running on ${address}` );
}
);
}
}