[mod] main

This commit is contained in:
roydfalk 2024-08-21 15:07:27 +02:00
parent a47162a8a0
commit 045330759b

View file

@ -3,6 +3,7 @@
*/
type type_conf = {
server : {
host : string;
port : int;
};
authentication : {
@ -20,31 +21,35 @@ type type_conf = {
type type_user_list_sparse = (
null
|
Record<
string,
{
disabled ?: boolean;
displayname ?: string;
email ?: string;
groups ?: Array<string>;
password : string;
}
>
{
users : Record<
string,
{
disabled ?: boolean;
displayname ?: string;
email ?: string;
groups ?: Array<string>;
password : string;
}
>;
}
);
/**
*/
type type_user_list_complete = Record<
string,
{
disabled : boolean;
displayname : string;
email : string;
groups : Array<string>;
password : string;
}
>;
type type_user_list_complete = {
users : Record<
string,
{
disabled : boolean;
displayname : string;
email : string;
groups : Array<string>;
password : string;
}
>;
};
/**
@ -54,41 +59,65 @@ async function conf_get(
) : Promise<type_conf>
{
const raw : any = lib_plankton.json.decode(await lib_plankton.file.read(path));;
return {
"server": {
"port": ((raw["server"] ?? {})["port"] ?? 4466),
},
"authentication": {
"timestamp_tolerance": (raw["authentication"]["timestamp_tolerance"] ?? 2.0),
"hash_salt": raw["authentication"]["hash_salt"], // required
},
"authelia": {
"usersfile_path": ((raw["authelia"] ?? {})["usersfile_path"] ?? "/var/authelia/users.yaml"),
},
};
const version_fallback : int = 1;
if (! ("version" in raw)) {
lib_plankton.log.warning(
"conf_version_unspecified",
{
"assumed_version": version_fallback,
}
);
}
else {
// do nothing
}
const version : int = (raw["version"] ?? version_fallback);
switch (version) {
default: {
throw (new Error("invalid version: " + version.toFixed(0)));
break;
}
case 1: {
return {
"server": {
"host": ((raw["server"] ?? {})["host"] ?? "::"),
"port": ((raw["server"] ?? {})["port"] ?? 7463),
},
"authentication": {
"timestamp_tolerance": (raw["authentication"]["timestamp_tolerance"] ?? 2.0),
"hash_salt": raw["authentication"]["hash_salt"], // required
},
"authelia": {
"usersfile_path": ((raw["authelia"] ?? {})["usersfile_path"] ?? "/var/authelia/users.yaml"),
},
};
break;
}
}
}
/**
*/
function encode_user_list(
user_list : type_user_list_sparse
user_list : (null | type_user_list_sparse)
) : string
{
let output : string = "";
Object.entries(user_list ?? {}).forEach(
output += "users:\n";
Object.entries((user_list === null) ? {} : user_list.users).forEach(
([key, value]) => {
output += (key + ":\n");
output += (" " + "disabled: " + ((value.disabled ?? false) ? "true" : "false") + "\n");
output += (" " + "displayname: " + (value.displayname ?? key) + "\n");
output += (" " + key + ":\n");
output += (" " + "disabled: " + ((value.disabled ?? false) ? "true" : "false") + "\n");
output += (" " + "displayname: " + (value.displayname ?? key) + "\n");
if ("email" in value) {
output += (" " + "email: " + value.email + "\n");
output += (" " + "email: " + value.email + "\n");
}
else {
// do nothing
}
output += (" " + "groups: " + JSON.stringify(value.groups ?? []) + "\n");
output += (" " + "password: " + value.password + "\n");
output += (" " + "groups: " + JSON.stringify(value.groups ?? []) + "\n");
output += (" " + "password: " + value.password + "\n");
}
);
return output;
@ -228,42 +257,52 @@ async function main(
"input_schema": () => ({
"nullable": true,
"type": "object",
"additionalProperties": {
"nullable": false,
"type": "object",
"additionalProperties": false,
"properties": {
"disabled": {
"additionalProperties": false,
"properties": {
"users": {
"nullable": true,
"type": "object",
"additionalProperties": {
"nullable": false,
"type": "boolean",
"type": "object",
"additionalProperties": false,
"properties": {
"disabled": {
"nullable": false,
"type": "boolean",
},
"displayname": {
"nullable": false,
"type": "string",
},
"email": {
"nullable": false,
"type": "string",
},
"groups": {
"nullable": false,
"type": "array",
"items": {
"nullable": false,
"type": "string"
}
},
"password": {
"nullable": false,
"type": "string",
},
},
"required": [
"password",
]
},
"displayname": {
"nullable": false,
"type": "string",
},
"email": {
"nullable": false,
"type": "string",
},
"groups": {
"nullable": false,
"type": "array",
"items": {
"nullable": false,
"type": "string"
}
},
"password": {
"nullable": false,
"type": "string",
},
},
"required": [
"password",
]
"properties": {},
"required": [],
}
},
"properties": {},
"required": [],
"required": [
"users"
]
}),
"output_schema": () => ({
"nullable": true,
@ -272,6 +311,13 @@ async function main(
const timestamp_local : float = lib_plankton.base.get_current_timestamp();
const timestamp_remote : float = parseFloat(stuff.query_parameters["timestamp"]);
if (Math.abs(timestamp_local - timestamp_remote) > conf.authentication.timestamp_tolerance) {
lib_plankton.log.notice(
"restriction_access_denied_due_to_invalid_timestamp",
{
"timestamp_local": timestamp_local,
"timestamp_remote": timestamp_remote,
}
);
return false;
}
else {
@ -280,6 +326,14 @@ async function main(
timestamp_remote.toFixed(0) + conf.authentication.hash_salt
);
if (authhash_is !== authhash_shall) {
lib_plankton.log.notice(
"restriction_access_denied_due_to_mismatching_hashes",
{
"timestamp": timestamp_remote,
"authhash_is": authhash_is,
"authhash_shall": authhash_shall,
}
);
return false;
}
else {
@ -292,6 +346,11 @@ async function main(
conf.authelia.usersfile_path,
encode_user_list(stuff.input)
);
lib_plankton.log.notice(
"userdata_updated",
{
}
);
return Promise.resolve({
"status_code": 200,
"data": null
@ -302,15 +361,43 @@ async function main(
}
const server : lib_plankton.server.type_subject = lib_plankton.server.make(
conf.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
const http_request : lib_plankton.http.type_request = lib_plankton.http.decode_request(input.toString());
return (
lib_plankton.rest.call(
rest_subject,
http_request
)
.catch(
(error) => {
lib_plankton.log.error(
"server_request_processing_failed",
{
"error": String(error),
}
);
return Promise.resolve<lib_plankton.http.type_response>(
{
"version": "HTTP/1.1",
"status_code": 500,
"headers": {},
// @ts-ignore
"body": Buffer.from(""),
}
);
}
)
.then<string>(
(http_response) => {
const output : string = lib_plankton.http.encode_response(http_response);
return Promise.resolve<string>(output);
}
)
);
const output : string = lib_plankton.http.encode_response(http_response);
return output;
},
{
"host": conf.server.host,
"port": conf.server.port,
}
);