/* 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.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 { 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> { return ( ( (await _espe.repository.admin.list(null)) .map(hit => hit.preview["email_address"]) .filter(x => (x !== null)) ) as Array ); } /** */ export async function notify_all( subject : string, body : string ) : Promise { return _espe.helpers.email_send( await email_addresses(), subject, body ); } }