/* Espe | Ein schlichtes Werkzeug zur Mitglieder-Verwaltung | Backend Copyright (C) 2024 Christian Fraß This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ namespace _espe.conf { /** */ type type_log_threshold = ( "debug" | "info" | "notice" | "warning" | "error" ); /** */ type type_log_format = ( "jsonl" | "human_readable" ); /** */ export type type_conf = { general : { language : (null | string); verification_secret : (null | string); }; log : Array< { kind : "stdout"; data : { threshold : type_log_threshold; }; } | { kind : "file"; data : { threshold : type_log_threshold; path : string; }; } | { kind : "email"; data : { threshold : type_log_threshold; smtp_credentials : { host : string; port : int; username : string; password : string; }; sender : string; receivers : Array; }; } >; server : { host : string; port : int; path_base : string; }; database : ( { kind : "sqlite"; data : { path : string; }; } | { kind : "postgresql"; data : { host : string; port ?: int; username : string; password : string; schema : string; }; } ); email_sending : ( { kind : "regular"; data : { smtp_credentials : _espe.helpers.type_smtp_credentials; sender : string; }; } | { kind : "redirect"; data : { smtp_credentials : _espe.helpers.type_smtp_credentials; sender : string; target : string; }; } | { kind : "console"; data : { }; } | { kind : "drop"; data : { }; } ); session_management : { in_memory : boolean; drop_all_at_start : boolean; lifetime : int; }; settings : { organisation : { name : string; domain : string; }; misc : { prefix_for_veiled_email_addresses : string; facultative_membership_number : boolean; auto_register : boolean; }; summon_email : { remark : string; }; password_policy : { minimum_length : (null | int); maximum_length : (null | int); must_contain_letter : boolean; must_contain_number : boolean; must_contain_special_character : boolean; }; password_change : { cooldown_time : int; }; name_index : { veil : boolean; salt : (null | string); }; connections : { frontend_url_base : (null | string); login_url : (null | string); }; }; // TODO: evtl. in Datenbank verlagern admins : Array< { name : string; password_image : string; email_address : (null | string); } >; outputs : Array< { kind : "authelia_file"; data : { path : string; } } | { kind : "http"; data : { scheme : ("http" | "https"); host : string; path : string; method : ("get" | "post" | "put" | "patch" | "delete" | "head" | "options"); query : (null | string); headers : Record; }; } | { kind : "arc"; data : { http_scheme : ("http" | "https"); http_host : string; http_port : int; hash_salt : string; } } >; }; /** */ var _data : (null | type_conf) = null; /** */ export function inject( conf_raw : any ) : void { const version : int = (conf_raw["version"] ?? 4); _data = { "general": ( ((node_general) => ({ "language": (node_general["language"] ?? null), "verification_secret": (node_general["verification_secret"] ?? null), })) (conf_raw["general"] ?? {}) ), "log": ( (() => { switch (version) { case 1: { return [ { "kind": "stdout", "data": { "threshold": ((conf_raw["general"] ?? {})["verbosity"] ?? "notice"), } }, ]; break; } case 2: case 3: case 4: { const node_log = ( conf_raw["log"] ?? [ { "kind": "stdout", "data": { } }, ] ); return ( node_log.map( (node_log_entry : any) => ({ "kind": node_log_entry["kind"], "data": Object.assign( { "format": "human_readable", "threshold": "notice", }, (node_log_entry["data"] ?? {}) ) }) ) ); break; } } }) () ), "server": ( ((node_server) => ({ "host": (() => { switch (version) { case 1: case 2: case 3: { return "::"; break; } case 4: { return (node_server["host"] ?? "::"); break } } }) (), "port": (node_server["port"] ?? 4916), "path_base": (node_server["path_base"] ?? ""), })) (conf_raw["server"] ?? {}) ), "database": ( ((node_database) => { const kind : string = (node_database["kind"] ?? "sqlite"); const node_database_data_raw = (node_database["data"] ?? {}); switch (kind) { case "sqlite": { return { "kind": kind, "data": { "path": (node_database_data_raw["path"] ?? "data.sqlite"), } }; break; } case "postgresql": { return { "kind": kind, "data": node_database_data_raw, }; break; } default: { throw (new Error("unhandled")); break; } } }) (conf_raw["database"] ?? {}) ), "email_sending": ( ((node_email_sending) => { const kind : string = (node_email_sending["kind"] ?? "console"); const data_raw = (node_email_sending["data"] ?? {}); switch (kind) { case "regular": { return { "kind": kind, "data": { "smtp_credentials": (data_raw["smtp_credentials"] ?? null), "sender": data_raw["sender"], } }; break; } case "redirect": { return { "kind": kind, "data": { "smtp_credentials": (data_raw["smtp_credentials"] ?? null), "sender": data_raw["sender"], "target": data_raw["target"], } }; break; } case "console": { return { "kind": kind, "data": { } }; break; } case "drop": { return { "kind": kind, "data": { } }; break; } default: { throw (new Error("unhandled")); break; } } }) (conf_raw["email_sending"] ?? {}) ), "session_management": ( ((node_session_management) => ({ "in_memory": (node_session_management["in_memory"] ?? true), "drop_all_at_start": (node_session_management["drop_all_at_start"] ?? true), "lifetime": (node_session_management["lifetime"] ?? 900), })) (conf_raw["session_management"] ?? {}) ), "settings": ( ((node_settings) => ({ "organisation": { "name": ((node_settings["organisation"] ?? {})["name"] ?? "Example Orginsation"), // TODO: mandatory? "domain": ((node_settings["organisation"] ?? {})["domain"] ?? "example.org"), // TODO: mandatory? }, "misc": ( ((node_settings_misc) => ({ "prefix_for_veiled_email_addresses": (node_settings_misc["prefix_for_veiled_email_addresses"] ?? "member-"), "facultative_membership_number": (node_settings_misc["facultative_membership_number"] ?? false), "auto_register": (node_settings_misc["auto_register"] ?? false), })) (node_settings["misc"] ?? {}) ), "summon_email": ( ((node_settings_summon_email) => ({ "remark": (node_settings_summon_email["remark"] ?? null), })) (node_settings["summon_email"] ?? {}) ), "password_policy": ( ((node_settings_password_policy) => ({ "minimum_length": ( ("minimum_length" in node_settings_password_policy) ? node_settings_password_policy["minimum_length"] : 8 ), "maximum_length": ( ("maximum_length" in node_settings_password_policy) ? node_settings_password_policy["maximum_length"] : 240 ), "must_contain_letter": (node_settings_password_policy["must_contain_letter"] ?? true), "must_contain_number": (node_settings_password_policy["must_contain_number"] ?? true), "must_contain_special_character": (node_settings_password_policy["must_contain_special_character"] ?? true), })) (node_settings["password_policy"] ?? {}) ), "password_change": ( ((node_settings_password_change) => ({ "cooldown_time": (node_settings_password_change["cooldown_time"] ?? 86400), })) (node_settings["password_change"] ?? {}) ), "name_index": ( ((node_settings_password_policy) => ({ "veil": (node_settings_password_policy["veil"] ?? true), "salt": (node_settings_password_policy["salt"] ?? ""), })) (node_settings["name_index"] ?? {}) ), "connections": ( ((node_settings_connections) => ({ "frontend_url_base": (node_settings_connections["frontend_url_base"] ?? null), "login_url": (node_settings_connections["login_url"] ?? null), })) (node_settings["connections"] ?? {}) ), })) (conf_raw["settings"] ?? {}) ), "admins": (conf_raw["admins"] ?? []), "outputs": (() => { switch (version) { case 1: case 2: { const node_output = (conf_raw["output"] ?? {}); return ( ("authelia" in node_output) ? [ { "kind": "authelia_file", "data": { "path": node_output["authelia"], } } ] : [ ] ); break; } case 3: { return (conf_raw["outputs"] ?? []); break; } case 4: { const node_outputs = (conf_raw["outputs"] ?? []); return node_outputs.map( (output_description : {kind : string; data : any;}) => { const kind : string = output_description["kind"]; const node_options_data_raw = (output_description["data"] ?? {}); switch (kind) { case "authelia_file": { return { "kind": kind, "data": { "path": (node_options_data_raw["path"] ?? "/var/authelia/users.yaml"), } }; break; } case "http": { return { "kind": kind, "data": { "scheme": (node_options_data_raw["scheme"] ?? "http"), "host": (node_options_data_raw["host"] ?? "localhost"), "path": (node_options_data_raw["path"] ?? ""), "method": (node_options_data_raw["method"] ?? "post"), "query": (node_options_data_raw["query"] ?? null), "headers": (node_options_data_raw["headers"] ?? {"Content-Type": "application/json"}), }, }; break; } case "arc": { return { "kind": kind, "data": { "http_scheme": (node_options_data_raw["scheme"] ?? "http"), "http_host": (node_options_data_raw["http_host"] ?? "localhost"), "http_port": (node_options_data_raw["http_port"] ?? 7463), "hash_salt": node_options_data_raw["hash_salt"], } }; break; } default: { throw (new Error("unhandled")); break; } } } ); break; } } }) (), }; } /** * @todo mandatory fields */ export async function load( path : string ) : Promise { let conf_raw : any; if (! (await lib_plankton.file.exists(path))) { // return Promise.reject(new Error("configuration file not found: " + path + "; using fallback")); conf_raw = {}; } else { try { conf_raw = lib_plankton.json.decode(await lib_plankton.file.read(path)); } catch (error) { conf_raw = null; } } if (conf_raw === null) { return Promise.reject("configuration file could not be read"); } else { inject(conf_raw); // process.stderr.write(JSON.stringify(_data, undefined, "\t")); return Promise.resolve(undefined); } } /** */ export function get( ) : type_conf { if (_data === null) { throw (new Error("conf not loaded yet")); } else { return _data; } } }