/* 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 . */ /** */ async function main( args_raw : Array ) : Promise { // init lib_plankton.log.conf_push( [ lib_plankton.log.channel_make( { "kind": "stdout", "data": { "threshold": "notice", // "format": "human_readable", } } ), ] ); const language_codes : Array = [ "deu", "eng", ]; await ( Promise.all( language_codes .map( language_code => ( lib_plankton.file.read( lib_plankton.string.coin( "data/localization/{{language_code}}.loc.json", { "language_code": language_code, } ) ) .then( content => (new Promise( (resolve, reject) => { try { resolve(JSON.parse(content)); } catch (error) { reject(error); } } )) ) ) ) ) .then( packages => lib_plankton.translate.initialize( { "verbosity": 1, "packages": packages, "order": language_codes, "autopromote": false, } ) ) ); // args const arg_handler : lib_plankton.args.class_handler = new lib_plankton.args.class_handler({ "action": lib_plankton.args.class_argument.positional({ "index": 0, "type": lib_plankton.args.enum_type.string, "mode": lib_plankton.args.enum_mode.replace, "default": "serve", "name": "action", "info": lib_plankton.string.coin( "{{description}}:\n{{options}}\n\t\t", { "description": lib_plankton.translate.get("help.args.action.options.serve"), "options": ( [ { "name": "serve", "description": lib_plankton.translate.get("help.args.action.options.serve"), }, { "name": "api-doc", "description": lib_plankton.translate.get("help.args.action.options.api_doc") }, { "name": "email-test", "description": lib_plankton.translate.get("help.args.action.options.email_test") }, { "name": "expose-conf", "description": lib_plankton.translate.get("help.args.action.options.expose_conf") }, { "name": "password-image", "description": lib_plankton.translate.get("help.args.action.options.password_image") }, { "name": "export-authelia", "description": lib_plankton.translate.get("help.args.action.options.export_authelia") }, { "name": "help", "description": lib_plankton.translate.get("help.args.action.options.help") }, ] .map( entry => lib_plankton.string.coin( "\t\t- {{name}}\n\t\t\t{{description}}\n", { "name": entry.name, "description": entry.description, } ) ) .join("") ), } ), }), "arg1": lib_plankton.args.class_argument.positional({ "index": 1, "type": lib_plankton.args.enum_type.string, "mode": lib_plankton.args.enum_mode.replace, "default": null, // "info": null, "name": "arg1", "hidden": true, }), "arg2": lib_plankton.args.class_argument.positional({ "index": 2, "type": lib_plankton.args.enum_type.string, "mode": lib_plankton.args.enum_mode.replace, "default": null, // "info": null, "name": "arg2", "hidden": true, }), "conf_path": lib_plankton.args.class_argument.volatile({ "indicators_long": ["conf_path"], "indicators_short": ["c"], "type": lib_plankton.args.enum_type.string, "mode": lib_plankton.args.enum_mode.replace, "default": "conf.json", "info": lib_plankton.translate.get("help.args.conf_path.description"), "name": "conf-path", }), "help": lib_plankton.args.class_argument.volatile({ "indicators_long": ["help"], "indicators_short": ["h"], "type": lib_plankton.args.enum_type.boolean, "mode": lib_plankton.args.enum_mode.replace, "default": false, "info": lib_plankton.translate.get("help.args.help.description"), "name": "help", }), }); const args : Record = arg_handler.read(lib_plankton.args.enum_environment.cli, args_raw.join(" ")); // init await _espe.conf.load(args["conf_path"]); if (_espe.conf.get().general.language === null) { // do nothing } else { lib_plankton.translate.promote(_espe.conf.get().general.language); } lib_plankton.log.conf_push( _espe.conf.get().log.map( log_output => lib_plankton.log.channel_make( { "kind": log_output.kind, "data": log_output.data } ) ) ); // exec if (args["help"] || (args["action"] === "help")) { process.stdout.write( arg_handler.generate_help( { "programname": "espe", "description": "Espe | Backend", "executable": "espe", } ) + "\n" ); } else { switch (args["action"]) { default: { process.stderr.write("invalid action: " + args["action"] + "\n"); break; } case "password-image": { const input : (null | string) = args["arg1"]; if (input === null) { throw (new Error("SYNTAX: password-image ")); } else { const result : string = await _espe.helpers.bcrypt_compute(input); process.stdout.write(result + "\n") } break; } case "expose-conf": { process.stdout.write( JSON.stringify( _espe.conf.get(), undefined, "\t" ) + "\n" ); break; } case "api-doc": { lib_plankton.log.conf_push([]); const rest_subject : lib_plankton.rest.type_rest = _espe.api.make(); lib_plankton.log.conf_pop(); process.stdout.write( JSON.stringify( lib_plankton.rest.to_oas(rest_subject), undefined, "\t" ) ); break; } case "email-test": { await _espe.helpers.email_send( ( (args["arg1"] !== null) ? [args["arg1"]] : ( ( _espe.conf.get().admins .map(admin => admin.email_address) .filter(x => (x !== null)) ) as Array ) ), lib_plankton.string.coin( "{{head}} | Test", { "head": _espe.conf.get().settings.organisation.name, } ), "This is a test e-mail" ); break; } case "serve": { // prepare database await _espe.database.check(); await lib_plankton.session.setup( { "data_chest": ( _espe.conf.get().session_management.in_memory ? lib_plankton.storage.memory.implementation_chest({}) : lib_plankton.call.convey( lib_plankton.storage.sql_table_common.chest( { "database_implementation": _espe.helpers.database_implementation(), "table_name": "sessions", "key_names": ["key"], } ), [ (core) => ({ "setup": (input) => core.setup(undefined), "clear": () => core.clear(), "write": (key, value) => core.write([key], {"data": JSON.stringify(value)}), "delete": (key) => core.delete([key]), "read": (key) => core.read([key]).then(row => JSON.parse(row["data"])), // "search": (term) => core.search(term).then(() => []), "search": (term) => Promise.reject(new Error("not implemented")), }), ] ) ), "default_lifetime": _espe.conf.get().session_management.lifetime, } ); _espe.service.member.listen_change( () => { lib_plankton.log.info( "member_change", { } ); } ); // outputs { _espe.conf.get().outputs.forEach( output_description => { switch (output_description.kind) { default: { lib_plankton.log.warning( "output_kind_unhandled", { "description": output_description, } ); break; } case "authelia_file": { _espe.service.member.output_authelia_file(output_description.data); break; } case "http": { _espe.service.member.output_http(output_description.data); break; } case "authelia_call": { _espe.service.member.output_authelia_call(output_description.data); break; } } } ); } const rest_subject : lib_plankton.rest.type_rest = _espe.api.make(); const server : lib_plankton.server.type_subject = lib_plankton.server.make( _espe.conf.get().server.port, async (input, metadata) => { const http_request : lib_plankton.http.type_request = lib_plankton.http.decode_request(input); const http_response : lib_plankton.http.type_response = await lib_plankton.rest.call( rest_subject, http_request, { "checklevel_restriction": lib_plankton.api.enum_checklevel.hard, // "checklevel_input": lib_plankton.api.enum_checklevel.soft, // "checklevel_output": lib_plankton.api.enum_checklevel.soft, } ); const output : string = lib_plankton.http.encode_response(http_response); return output; } ); lib_plankton.server.start(server); break; } case "export-authelia": { process.stdout.write(await _espe.service.member.export_authelia_user_file() + "\n"); break; } } } } ( main(process.argv.slice(2)) .then( () => { } ) .catch( (error) => { process.stderr.write(String(error) + "\n"); } ) );