163 lines
3.6 KiB
TypeScript
163 lines
3.6 KiB
TypeScript
/*
|
|
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/>.
|
|
*/
|
|
|
|
namespace _espe.service.admin
|
|
{
|
|
|
|
/**
|
|
*/
|
|
export type type_value = {
|
|
id : _espe.type.admin_id;
|
|
object : _espe.type.admin_object;
|
|
};
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function add(
|
|
name : string,
|
|
email_address : (null | string),
|
|
password : string
|
|
) : Promise<_espe.type.admin_id>
|
|
{
|
|
const admin_object : _espe.type.admin_object = {
|
|
"name": name,
|
|
"email_address": email_address,
|
|
"password_image": (await _espe.helpers.bcrypt_compute(password)),
|
|
"password_fail_count": 0,
|
|
};
|
|
return _espe.repository.admin.create(admin_object);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
async function get(
|
|
name : string
|
|
) : Promise<(null | type_value)>
|
|
{
|
|
const hits : Array<
|
|
{
|
|
id : _espe.type.admin_id;
|
|
preview : _espe.type.admin_object;
|
|
}
|
|
> = await _espe.repository.admin.list(name);
|
|
return Promise.resolve<(null | type_value)>(
|
|
(hits.length === 1)
|
|
?
|
|
{"id": hits[0].id, "object": hits[0].preview}
|
|
:
|
|
null
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
async function check_password(
|
|
value : type_value,
|
|
password_given : string
|
|
) : Promise<boolean>
|
|
{
|
|
return _espe.helpers.bcrypt_compare(value.object.password_image, password_given);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function login(
|
|
name : string,
|
|
password : string
|
|
) : Promise<(null | type_value)>
|
|
{
|
|
const value : (null | type_value) = await get(name);
|
|
if (value === null) {
|
|
return null;
|
|
}
|
|
else {
|
|
/**
|
|
* @todo outsource fail count threshold?
|
|
*/
|
|
const password_fail_threshold : int = 3;
|
|
if (value.object.password_fail_count >= password_fail_threshold) {
|
|
lib_plankton.log.notice(
|
|
"admin_password_fail_threshold_exceeded",
|
|
{
|
|
"id": value.id,
|
|
"name": value.object.name,
|
|
"password_fail_count": (value.object.password_fail_count + 1)
|
|
}
|
|
);
|
|
await _espe.repository.admin.update(
|
|
value.id,
|
|
{
|
|
"name": value.object.name,
|
|
"email_address": value.object.email_address,
|
|
"password_image": value.object.password_image,
|
|
"password_fail_count": (value.object.password_fail_count + 1),
|
|
}
|
|
);
|
|
return null;
|
|
}
|
|
else {
|
|
if (! (await check_password(value, password))) {
|
|
await _espe.repository.admin.update(
|
|
value.id,
|
|
{
|
|
"name": value.object.name,
|
|
"email_address": value.object.email_address,
|
|
"password_image": value.object.password_image,
|
|
"password_fail_count": (value.object.password_fail_count + 1),
|
|
}
|
|
);
|
|
return null;
|
|
}
|
|
else {
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*/
|
|
export async function email_addresses(
|
|
) : Promise<Array<string>>
|
|
{
|
|
return (
|
|
(
|
|
(await _espe.repository.admin.list(null))
|
|
.map(hit => hit.preview["email_address"])
|
|
.filter(x => (x !== null))
|
|
) as Array<string>
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function notify_all(
|
|
subject : string,
|
|
body : string
|
|
) : Promise<void>
|
|
{
|
|
return _espe.helpers.email_send(
|
|
await email_addresses(),
|
|
subject,
|
|
body
|
|
);
|
|
}
|
|
|
|
}
|