backend/source/services/member.ts

852 lines
20 KiB
TypeScript
Raw Normal View History

2024-05-20 21:56:48 +02:00
/*
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
<https://www.gnu.org/licenses/>.
*/
2024-04-22 10:22:18 +02:00
namespace _espe.service.member
2024-04-22 10:02:34 +02:00
{
/**
*/
var _hooks_change : Array<() => void> = [];
/**
*/
export function listen_change(
procedure : () => void
) : void
{
_hooks_change.push(procedure);
}
/**
*/
2024-05-27 21:27:36 +02:00
function signal_change(
2024-04-22 10:02:34 +02:00
) : void
{
_hooks_change.forEach(
procedure => {
procedure();
}
);
}
2024-04-30 14:05:01 +02:00
/**
*/
2025-07-03 08:53:05 +00:00
export function validate_password(
2024-04-30 14:05:01 +02:00
password : string
) : Array<{incident : string; details : Record<string, any>}>
{
2024-06-20 15:13:58 +02:00
return _espe.helper.password.validate(
_espe.conf.get().settings.password_policy,
password
);
}
/**
*/
2025-07-03 08:53:05 +00:00
export function generate_password(
2024-06-20 15:13:58 +02:00
) : string
{
return _espe.helper.password.generate(
_espe.conf.get().settings.password_policy
);
2024-04-30 14:05:01 +02:00
}
2024-04-22 10:02:34 +02:00
/**
2024-05-20 09:52:09 +02:00
* ermittelt den Anmelde-Name des Mitglieds
2024-04-22 10:02:34 +02:00
*/
2024-04-30 08:46:52 +02:00
export function name_login(
2024-04-29 22:40:52 +02:00
object : _espe.type.member_object
) : string
{
return lib_plankton.string.coin(
"{{object}}{{extension}}",
{
2024-04-30 14:05:01 +02:00
"object": lib_plankton.call.convey(
2025-07-07 12:10:52 +02:00
object.name,
2024-04-30 14:05:01 +02:00
[
2024-05-27 17:32:42 +02:00
(x : string) => x.toLowerCase(),
(x : string) => x.replace(new RegExp(" ", "g"), "."),
(x : string) => x.replace(new RegExp("[äÄ]", "g"), "ae"),
(x : string) => x.replace(new RegExp("[öÖ]", "g"), "oe"),
(x : string) => x.replace(new RegExp("[üÜ]", "g"), "ue"),
(x : string) => x.replace(new RegExp("[ß]", "g"), "ss"),
(x : string) => x.replace(new RegExp("[^0-9a-z-\.]", "g"), "_"),
2024-04-30 14:05:01 +02:00
]
),
2025-07-07 12:10:52 +02:00
"extension": "",
2024-04-29 22:40:52 +02:00
}
);
}
/**
2024-05-20 09:52:09 +02:00
* ermittelt den Anzeige-Name des Mitglieds
2024-04-29 22:40:52 +02:00
*/
2024-04-30 08:46:52 +02:00
export function name_display(
2024-04-29 22:40:52 +02:00
object : _espe.type.member_object
) : string
{
2025-07-07 12:10:52 +02:00
return object.name;
2024-04-29 22:40:52 +02:00
}
/**
2024-05-20 09:52:09 +02:00
* ermittelt die allgemein zu verwendende E-Mail-Adresse des Mitglieds
2024-04-29 22:40:52 +02:00
*/
2024-04-30 08:46:52 +02:00
export function email_address(
2024-04-29 22:40:52 +02:00
object : _espe.type.member_object
) : (null | string)
{
2025-07-07 12:10:52 +02:00
return object.email_address;
2024-04-29 22:40:52 +02:00
}
/**
* ermittelt das Passwort-Abbild anhand des tatsächlichen Passworts
*/
function password_image(
password : (null | string)
2024-05-27 17:32:42 +02:00
) : Promise<(null | string)>
{
return (
(
(! (password === null))
&&
(! (password === ""))
)
? _espe.helpers.bcrypt_compute(password)
2024-05-27 17:32:42 +02:00
: Promise.resolve<(null | string)>(null)
);
}
2024-05-27 21:27:36 +02:00
/**
*/
async function send_activation_email(
member_object : _espe.type.member_object,
options : {
password ?: (null | string);
} = {}
2024-05-27 21:27:36 +02:00
) : Promise<void>
{
options = Object.assign(
{
"password": null,
},
options
);
2024-05-27 21:27:36 +02:00
if (! member_object.enabled) {
// do nothing
}
else {
2025-07-07 12:10:52 +02:00
if (member_object.email_address === null)
{
2024-05-27 21:27:36 +02:00
// do nothing
}
2025-07-07 12:10:52 +02:00
else
{
2024-05-27 21:27:36 +02:00
await _espe.helpers.email_send(
[
2025-07-07 12:10:52 +02:00
member_object.email_address,
2024-05-27 21:27:36 +02:00
],
lib_plankton.string.coin(
2024-06-03 12:33:15 +02:00
"{{head}} | {{core}}",
{
"head": _espe.conf.get().settings.organisation.name,
"core": lib_plankton.translate.get("email.activation.subject"),
}
),
lib_plankton.string.coin(
lib_plankton.translate.get("email.activation.body"),
2024-05-27 21:27:36 +02:00
{
"name_display": name_display(member_object),
"name_login": name_login(member_object),
2024-06-03 12:33:15 +02:00
"url": (_espe.conf.get().settings.connections.login_url ?? "--"),
"password_info": (
(
(options.password === undefined)
||
(options.password === null)
)
? ""
: lib_plankton.string.coin(
lib_plankton.translate.get("email.activation.password_info"),
{
"password": options.password,
}
)
),
2024-05-27 21:27:36 +02:00
}
)
);
}
}
}
2024-04-29 22:40:52 +02:00
/**
2024-05-20 09:52:09 +02:00
* gibt die vollständigen Daten aller Mitglieder aus
2024-04-29 22:40:52 +02:00
*/
2024-08-18 13:54:58 +02:00
export async function dump(
2024-04-29 22:40:52 +02:00
) : Promise<
Array<
{
id : _espe.type.member_id;
object : _espe.type.member_object;
}
>
>
{
return _espe.repository.member.dump();
}
2024-04-30 01:32:24 +02:00
/**
2024-05-20 09:52:09 +02:00
* gibt eine Auflistung aller Mitgliedr aus
2024-04-30 01:32:24 +02:00
*/
export async function list(
search_term : (null | string)
) : Promise<
Array<
{
id : _espe.type.member_id;
preview : {
2025-07-07 12:10:52 +02:00
name : string;
2024-04-30 01:32:24 +02:00
};
}
>
>
{
return _espe.repository.member.list(search_term);
}
2024-04-29 22:40:52 +02:00
/**
2024-05-20 09:52:09 +02:00
* gibt die Angaben eines bestimmten Mitglieds aus
2024-04-29 22:40:52 +02:00
*/
2024-04-30 01:32:24 +02:00
export function get(
2024-04-29 22:40:52 +02:00
id : _espe.type.member_id
) : Promise<_espe.type.member_object>
{
return _espe.repository.member.read(id);
}
/**
2024-05-20 09:52:09 +02:00
* legt ein Mitglied an
2024-04-29 22:40:52 +02:00
*/
export async function project(
2024-04-29 20:48:20 +02:00
data : {
2025-07-07 12:10:52 +02:00
name : string;
email_address : (null | string);
groups : Array<_espe.type.group_id>;
},
{
"silent": silent = false,
} : {
silent ?: boolean;
} = {
2024-04-29 20:48:20 +02:00
}
2024-04-29 22:40:52 +02:00
) : Promise<_espe.type.member_id>
2024-04-22 10:02:34 +02:00
{
2024-04-29 22:40:52 +02:00
const object : _espe.type.member_object = {
2025-07-07 12:10:52 +02:00
"name": data.name,
"email_address": data.email_address,
"groups": data.groups,
2024-04-30 15:35:17 +02:00
"enabled": true,
2024-04-29 20:48:20 +02:00
"password_image": null,
"password_change_last_attempt": null,
"password_change_token": null,
2024-04-22 10:02:34 +02:00
};
2024-04-29 22:40:52 +02:00
const id : _espe.type.member_id = await _espe.repository.member.create(object);
2025-07-07 12:10:52 +02:00
if (silent)
{
// do nothing
}
2025-07-07 12:10:52 +02:00
else
{
signal_change();
}
2024-04-29 20:48:20 +02:00
return id;
2024-04-22 10:02:34 +02:00
}
2025-07-03 08:53:05 +00:00
/**
* legt ein Mitglied an
*/
export async function add(
data : {
2025-07-07 12:10:52 +02:00
name : string;
email_address : (null | string);
groups : Array<_espe.type.group_id>;
2025-07-03 08:53:05 +00:00
password : string;
},
{
"silent": silent = false,
} : {
silent ?: boolean;
} = {
}
) : Promise<_espe.type.member_id>
{
const object : _espe.type.member_object = {
2025-07-07 12:10:52 +02:00
"name": data.name,
"email_address": data.email_address,
"groups": data.groups,
2025-07-03 08:53:05 +00:00
"enabled": true,
"password_image": await password_image(data.password),
"password_change_last_attempt": null,
"password_change_token": null,
};
const id : _espe.type.member_id = await _espe.repository.member.create(object);
if (silent)
{
// do nothing
}
else
{
signal_change();
}
return id;
}
2024-04-29 22:40:52 +02:00
/**
2024-05-20 09:52:09 +02:00
* sendet an ein Mitglied eine E-Mail mit Aufforderung zur Registrierung
2024-04-29 22:40:52 +02:00
*/
export async function summon(
member_id : _espe.type.member_id,
url_template : string
2024-05-27 17:32:42 +02:00
) : Promise<(null | string)>
2024-04-22 10:02:34 +02:00
{
2024-05-27 21:27:36 +02:00
_espe.helpers.frontend_url_check();
2024-04-29 22:40:52 +02:00
const member_object : _espe.type.member_object = await get(member_id);
2025-07-07 12:10:52 +02:00
if (member_object.email_address === null)
{
2024-05-27 17:32:42 +02:00
return null;
}
2025-07-07 12:10:52 +02:00
else
{
2024-05-27 21:27:36 +02:00
const url : (null | string) = _espe.helpers.frontend_url_get(
2024-05-27 17:32:42 +02:00
url_template,
2024-04-29 22:40:52 +02:00
{
2024-05-27 21:27:36 +02:00
"verification": await _espe.helpers.verification_get(member_id),
2024-04-29 22:40:52 +02:00
}
2024-05-27 17:32:42 +02:00
);
2024-05-27 21:27:36 +02:00
if (url === null) {
// do nothing
}
else {
await _espe.helpers.email_send(
[
2025-07-07 12:10:52 +02:00
member_object.email_address,
2024-05-27 21:27:36 +02:00
],
lib_plankton.string.coin(
2024-06-03 12:33:15 +02:00
"{{head}} | {{core}}",
{
"head": _espe.conf.get().settings.organisation.name,
"core": lib_plankton.translate.get("email.summon.subject"),
}
),
lib_plankton.string.coin(
lib_plankton.translate.get("email.summon.body"),
2024-05-27 21:27:36 +02:00
{
"name": name_display(member_object),
"url": url,
2024-06-03 12:33:15 +02:00
"remark": (
(_espe.conf.get().settings.summon_email.remark === null)
? ""
: (_espe.conf.get().settings.summon_email.remark + "\n\n")
),
2024-05-27 21:27:36 +02:00
}
)
);
}
2024-05-27 17:32:42 +02:00
return url;
}
2024-04-22 10:02:34 +02:00
}
2024-04-30 01:32:24 +02:00
/**
2024-05-20 09:52:09 +02:00
* ändert bestimmte Daten des Mitglied
2024-04-30 01:32:24 +02:00
*/
2024-04-29 22:40:52 +02:00
export async function modify(
2024-04-30 01:32:24 +02:00
member_id : _espe.type.member_id,
data : {
2025-07-07 12:10:52 +02:00
email_address : (null | string);
2024-04-30 01:32:24 +02:00
enabled : boolean;
2025-07-07 12:10:52 +02:00
groups : lib_plankton.pod.type_pod<Array<_espe.type.group_id>>;
2024-04-30 01:32:24 +02:00
}
2024-04-29 22:40:52 +02:00
) : Promise<void>
2024-04-22 10:02:34 +02:00
{
2024-04-30 01:32:24 +02:00
const member_object_old : _espe.type.member_object = await get(member_id);
const member_object_new : _espe.type.member_object = {
2025-07-07 12:10:52 +02:00
"name": member_object_old.name,
"email_address": data.email_address,
"groups": (
lib_plankton.pod.is_filled<Array<_espe.type.group_id>>(data.groups)
? lib_plankton.pod.cull<Array<_espe.type.group_id>>(data.groups)
: member_object_old.groups
),
2024-04-30 01:32:24 +02:00
"enabled": data.enabled,
"password_image": member_object_old.password_image,
"password_change_last_attempt": member_object_old.password_change_last_attempt,
"password_change_token": member_object_old.password_change_token,
2024-04-30 01:32:24 +02:00
};
await _espe.repository.member.update(member_id, member_object_new);
2024-05-27 21:27:36 +02:00
signal_change();
/*await*/ // send_activation_email(member_object_new);
2024-04-22 10:02:34 +02:00
}
/**
*/
export async function remove(
id : _espe.type.member_id
) : Promise<void>
{
await _espe.repository.member.delete_(id);
signal_change();
}
/**
* bereitet eine Passwort-Rücksetzung für Mitglieder vor
*
* @todo Zwangs-Pause falls Abklingzeit noch nicht vorbei um vorzugaukeln, dass es geklappt hat?
*/
export async function password_change_initialize(
identifier : string,
url_template : string
) : Promise<void>
{
2024-05-27 21:27:36 +02:00
_espe.helpers.frontend_url_check();
const now : int = lib_plankton.base.get_current_timestamp(true);
const cooldown_time : int = _espe.conf.get().settings.password_change.cooldown_time;
const member_ids : Array<_espe.type.member_id> = await (
(await _espe.repository.member.dump())
.filter(
member_entry => (
member_entry.object.enabled
&&
(
(
2025-07-07 12:10:52 +02:00
(! (member_entry.object.email_address === null))
2024-05-27 21:27:36 +02:00
&&
2025-07-07 12:10:52 +02:00
(member_entry.object.email_address === identifier)
)
2024-05-27 21:27:36 +02:00
||
(name_login(member_entry.object) === identifier)
)
)
2024-05-27 21:27:36 +02:00
)
.map(
member_entry => member_entry.id
)
);
for await (const member_id of member_ids) {
const member_object_old : _espe.type.member_object = await _espe.repository.member.read(member_id);
if (
(! (member_object_old.password_change_last_attempt === null))
&&
((now - member_object_old.password_change_last_attempt) <= cooldown_time)
) {
lib_plankton.log.notice(
"member_password_change_cooldown_not_over",
{
"member_id": member_id,
"last_attempt": member_object_old.password_change_last_attempt,
"now": now,
}
);
// do nothing
}
else {
2025-07-07 12:10:52 +02:00
if (member_object_old.email_address === null) {
lib_plankton.log.notice(
2025-07-07 12:10:52 +02:00
"member_password_change_impossible_due_to_missing_email_address",
{
"member_id": member_id,
}
);
// do nothing
}
else {
2024-05-27 21:27:36 +02:00
// keine echte Verifizierung, der Algorithmus ist aber der passende
const token : string = await _espe.helpers.verification_get(Math.floor(Math.random() * (1 << 24)));
const member_object_new : _espe.type.member_object = {
2025-07-07 12:10:52 +02:00
"name": member_object_old.name,
"email_address": member_object_old.email_address,
2024-05-27 21:27:36 +02:00
"enabled": member_object_old.enabled,
2025-07-07 12:10:52 +02:00
"groups": member_object_old.groups,
2024-05-27 21:27:36 +02:00
"password_image": member_object_old.password_image,
"password_change_last_attempt": now,
"password_change_token": token,
};
await _espe.repository.member.update(member_id, member_object_new);
// signal_change();
// do NOT wait in order to reduce information for potential attackers
const url : (null | string) = _espe.helpers.frontend_url_get(
url_template,
{
"id": member_id.toFixed(0),
"token": token,
}
);
if (url === null) {
// do nothing
}
else {
2024-05-20 14:06:54 +02:00
/*await*/ _espe.helpers.email_send(
[
2025-07-07 12:10:52 +02:00
member_object_old.email_address,
],
lib_plankton.string.coin(
2024-06-03 12:33:15 +02:00
"{{head}} | {{core}}",
{
"head": _espe.conf.get().settings.organisation.name,
"core": lib_plankton.translate.get("email.password_change.initialization.subject"),
}
),
lib_plankton.string.coin(
lib_plankton.translate.get("email.password_change.initialization.body"),
{
2024-05-20 14:06:54 +02:00
"name": name_display(member_object_old),
2024-05-27 21:27:36 +02:00
"url": url,
}
)
);
}
}
}
}
}
/**
* führt eine Passwort-Rücksetzung für ein Mitglied durch
*
* @todo zeitliche Begrenzung?
*/
export async function password_change_execute(
member_id : _espe.type.member_id,
token : string,
password_new : string
2024-05-20 14:06:54 +02:00
) : Promise<Array<{incident : string; details : Record<string, any>;}>>
{
const member_object_old : _espe.type.member_object = await _espe.repository.member.read(member_id);
2025-07-07 12:10:52 +02:00
if (member_object_old.email_address === null)
{
2024-05-27 17:32:42 +02:00
return Promise.reject(new Error("private e-mail address missing"));
}
2025-07-07 12:10:52 +02:00
else
{
2024-05-27 17:32:42 +02:00
let flaws : Array<{incident : string; details : Record<string, any>;}> = [];
if (
(member_object_old.password_change_token === null)
||
(! (token === member_object_old.password_change_token))
) {
lib_plankton.log.notice(
"member_password_change_token_invalid",
{
"member_id": member_id,
"token_sent": token,
}
);
flaws.push({"incident": "token_invalid", "details": {}});
2024-05-20 14:06:54 +02:00
}
else {
2024-05-27 17:32:42 +02:00
flaws = flaws.concat(
validate_password(password_new)
.map(flaw => ({"incident": ("password_" + flaw.incident), "details": flaw.details}))
2024-05-20 14:06:54 +02:00
);
2024-05-27 17:32:42 +02:00
if (flaws.length > 0) {
// do nothing
}
else {
const member_object_new : _espe.type.member_object = {
2025-07-07 12:10:52 +02:00
"name": member_object_old.name,
"email_address": member_object_old.email_address,
"groups": member_object_old.groups,
2024-05-27 17:32:42 +02:00
"enabled": member_object_old.enabled,
"password_image": await password_image(password_new),
"password_change_last_attempt": member_object_old.password_change_last_attempt,
"password_change_token": null,
};
await _espe.repository.member.update(member_id, member_object_new);
2024-05-27 21:27:36 +02:00
signal_change();
2024-05-27 17:32:42 +02:00
await _espe.helpers.email_send(
[
2025-07-07 12:10:52 +02:00
member_object_old.email_address,
2024-05-27 17:32:42 +02:00
],
lib_plankton.string.coin(
2024-06-03 12:33:15 +02:00
"{{head}} | {{core}}",
{
"head": _espe.conf.get().settings.organisation.name,
"core": lib_plankton.translate.get("email.password_change.execution.subject"),
}
),
lib_plankton.string.coin(
lib_plankton.translate.get("email.password_change.execution.body"),
2024-05-27 17:32:42 +02:00
{
"name": name_display(member_object_old),
}
)
);
}
2024-05-20 14:06:54 +02:00
}
2024-05-27 17:32:42 +02:00
return flaws;
}
}
2024-04-30 01:32:24 +02:00
2024-04-29 22:40:52 +02:00
/**
* @todo check validity (e.g. username characters)
2024-04-29 22:40:52 +02:00
*/
2024-08-18 13:54:58 +02:00
export async function export_authelia_user_data(
options : {
custom_data ?: (null | Array<_espe.type.member_object>);
} = {}
2024-08-18 13:54:58 +02:00
) : Promise<any>
2024-04-22 10:02:34 +02:00
{
options = Object.assign(
{
"custom_data": null,
},
options
);
2024-05-27 17:32:42 +02:00
type type_entry = {
disabled : boolean;
displayname : string;
email : string;
groups : Array<string>;
password : string;
};
2024-04-22 10:02:34 +02:00
return lib_plankton.call.convey(
(
2024-05-27 17:32:42 +02:00
(
(options.custom_data !== undefined)
&&
(options.custom_data !== null)
)
? (options.custom_data.map((member_object, index) => ({"id": index, "object": member_object})))
: await dump()
),
2024-04-22 10:02:34 +02:00
[
2024-05-27 17:32:42 +02:00
(x : Array<any>) => x.map(
2024-04-22 10:02:34 +02:00
entry => Object.assign(
entry,
2024-04-29 22:40:52 +02:00
{"email_address": email_address(entry.object)}
2024-04-22 10:02:34 +02:00
)
),
2024-05-27 17:32:42 +02:00
(x : Array<any>) => x.filter(
2024-04-22 10:02:34 +02:00
entry => (
2024-04-29 22:40:52 +02:00
entry.object.registered
2024-04-22 10:02:34 +02:00
&&
(
2024-04-29 22:40:52 +02:00
(entry.object.password_image !== null)
2024-04-22 10:02:34 +02:00
&&
2024-04-29 22:40:52 +02:00
(entry.object.password_image !== "")
2024-04-22 10:02:34 +02:00
)
&&
(entry.email_address !== null)
)
),
2024-05-27 17:32:42 +02:00
(x : Array<any>) => x.map(
2024-04-22 10:02:34 +02:00
entry => ([
2024-04-29 22:40:52 +02:00
name_login(entry.object),
2024-04-22 10:02:34 +02:00
{
2024-04-29 22:40:52 +02:00
"disabled": (! entry.object.enabled),
"displayname": name_display(entry.object),
2024-04-22 10:02:34 +02:00
"email": entry.email_address,
2025-07-07 12:10:52 +02:00
/**
* @todo covert to string
*/
2025-01-17 09:49:13 +01:00
"groups": entry.object.groups,
2024-04-29 22:40:52 +02:00
"password": entry.object.password_image,
2024-04-22 10:02:34 +02:00
}
])
),
Object.fromEntries,
2024-05-27 17:32:42 +02:00
(x : Record<string, type_entry>) => ({"users": x}),
2024-04-22 10:02:34 +02:00
]
);
}
2024-08-18 13:54:58 +02:00
/**
*/
export async function export_authelia_user_file(
options : {
custom_data ?: (null | Array<_espe.type.member_object>);
} = {}
) : Promise<string>
{
options = Object.assign(
{
"custom_data": null,
},
options
);
const nm_yaml = require("yaml");
return nm_yaml.stringify(await export_authelia_user_data(options));
}
/**
*/
export async function output_authelia_file(
output_parameters : {
path : string;
}
) : Promise<void>
{
await lib_plankton.file.write(
output_parameters.path,
await _espe.service.member.export_authelia_user_file()
);
}
/**
*/
export async function output_http(
output_parameters : {
scheme : ("http" | "https");
host : string;
path : string;
method : ("get" | "post" | "put" | "patch" | "delete" | "head" | "options");
query : (null | string);
headers : Record<string,string>;
}
) : Promise<void>
{
const http_request : lib_plankton.http.type_request = {
"scheme": output_parameters.scheme,
"host": output_parameters.host,
"path": output_parameters.path,
"version": "HTTP/1.1",
"method": (
(
{
"get": lib_plankton.http.enum_method.get,
"post": lib_plankton.http.enum_method.post,
"put": lib_plankton.http.enum_method.put,
"patch": lib_plankton.http.enum_method.patch,
"delete": lib_plankton.http.enum_method.delete,
"head": lib_plankton.http.enum_method.head,
"options": lib_plankton.http.enum_method.options,
}[output_parameters.method]
)
??
lib_plankton.http.enum_method.post
),
"query": output_parameters.query,
"headers": output_parameters.headers,
"body": lib_plankton.json.encode(await _espe.service.member.dump()),
};
const http_response : lib_plankton.http.type_response = await lib_plankton.http.call(
http_request
);
if (! ((http_response.status_code >= 200) && (http_response.status_code < 400))) {
lib_plankton.log.warning(
"output_http_failed",
{
"http_request": http_request,
"http_response_status_code": http_response.status_code,
}
);
}
else {
// do nothing
}
}
/**
*/
2024-08-22 08:04:45 +02:00
export async function output_arc(
2024-08-18 13:54:58 +02:00
output_parameters : {
http_scheme : ("http" | "https");
http_host : string;
2024-08-22 07:46:06 +02:00
http_port : int;
2024-08-18 13:54:58 +02:00
hash_salt : string;
}
) : Promise<void>
{
const timestamp : float = lib_plankton.base.get_current_timestamp();
const auth : string = lib_plankton.sha256.get(
timestamp.toFixed(0)
+
output_parameters.hash_salt
);
const http_request : lib_plankton.http.type_request = {
"scheme": output_parameters.http_scheme,
2024-08-22 07:46:06 +02:00
"host": lib_plankton.string.coin(
"{{host}}:{{port}}",
{
"host": output_parameters.http_host,
"port": output_parameters.http_port.toFixed(0),
}
),
2024-08-18 13:54:58 +02:00
"path": "/users/set",
"version": "HTTP/1.1",
"method": lib_plankton.http.enum_method.put,
"query": lib_plankton.string.coin(
"?timestamp={{timestamp}}&auth={{auth}}",
{
"timestamp": timestamp.toFixed(0),
"auth": auth,
}
),
"headers": {
"Content-Type": "application/json",
},
2024-08-21 15:18:40 +02:00
// @ts-ignore
"body": Buffer.from(
lib_plankton.json.encode(
(await _espe.service.member.export_authelia_user_data())
),
"utf8"
),
2024-08-18 13:54:58 +02:00
};
const http_response : lib_plankton.http.type_response = await lib_plankton.http.call(
http_request
);
if (http_response.status_code !== 200) {
lib_plankton.log.warning(
2025-01-17 09:49:13 +01:00
"output_arc_failed",
2024-08-18 13:54:58 +02:00
{
"http_response_status_code": http_response.status_code,
}
);
}
else {
// do nothing
}
}
2024-04-22 10:02:34 +02:00
}