/* This file is part of »zeitbild«. Copyright 2025 'kcf' »zeitbild« is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. »zeitbild« 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with »zeitbild«. If not, see . */ namespace _zeitbild.repository.user { /** */ type type_core_row = { name : string; email_address : (null | string); dav_token : (null | string); }; /** */ type type_group_row_slim = { group_id : int; }; /** */ type type_group_row_fat = { user_id : int; group_id : int; }; /** */ type type_preview = { name : string; }; /** */ type type_dispersal = { core : type_core_row; groups : Array; }; /** */ var _store_core : ( null | lib_plankton.storage.type_store< _zeitbild.type_user_id, /*type_core_row*/Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, /*type_preview*/Record > ) = null; /** */ var _store_groups : ( null | lib_plankton.storage.type_store< int, /*type_group_row_fat*/Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, Record > ) = null; /** */ function get_store_core( ) : lib_plankton.storage.type_store< _zeitbild.type_user_id, /*type_core_row*/Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, /*type_preview*/Record > { if (_store_core === null) { _store_core = lib_plankton.storage.sql_table_autokey_store( { "database_implementation": _zeitbild.database.get_implementation(), "table_name": "users", "key_name": "id", } ); } else { // do nothing } return _store_core; } /** */ function get_store_groups( ) : lib_plankton.storage.type_store< int, /*type_group_row_fat*/Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, Record > { if (_store_groups === null) { _store_groups = lib_plankton.storage.sql_table_autokey_store( { "database_implementation": _zeitbild.database.get_implementation(), "table_name": "user_groups", "key_name": "id", } ); } else { // do nothing } return _store_groups; } /** */ function encode( user_object : _zeitbild.type_user_object ) : type_dispersal { return { "core": { "name": user_object.name, "email_address": user_object.email_address, "dav_token": user_object.dav_token, }, "groups": ( user_object.groups.map( group_id => ( { "group_id": group_id, } ) ) ), }; } /** */ function decode( dispersal : type_dispersal ) : _zeitbild.type_user_object { return { "name": dispersal.core.name, "groups": ( dispersal.groups.map( group_row => group_row.group_id, ) ), "email_address": dispersal.core.email_address, "dav_token": dispersal.core.dav_token, }; } /** */ export async function list( ) : Promise< Array< { id : _zeitbild.type_user_id; name : string; } > > { const hits : Array<{key : int; preview : /*type_preview*/Record;}> = await get_store_core().search( { "expression": "TRUE", "arguments": {} } ); return Promise.resolve( hits .map( (hit) => ({ "id": hit.key, "name": hit.preview.name, }) ) ); } /** */ export async function read( user_id : _zeitbild.type_user_id ) : Promise<_zeitbild.type_user_object> { const core_row : type_core_row = ((await get_store_core().read(user_id)) as type_core_row); const group_rows : Array = ( ( await get_store_groups().search( { "expression": "(user_id = $user_id)", "arguments": { "user_id": user_id, } } ) ) .map( hit => ( { "user_id": hit.preview.user_id, "group_id": hit.preview.group_id, } ) ) ); const dispersal : type_dispersal = { "core": core_row, "groups": ( group_rows.map( group_row_fat => ( { "group_id": group_row_fat.group_id, } ) ) ) }; const user_object : _zeitbild.type_user_object = decode(dispersal); return Promise.resolve<_zeitbild.type_user_object>(user_object); } /** */ export async function create( user_object : _zeitbild.type_user_object ) : Promise<_zeitbild.type_user_id> { const dispersal : type_dispersal = encode(user_object); // core const user_id : _zeitbild.type_user_id = await (() => { return get_store_core().create(dispersal.core); }) (); // groups { for (const group_row_slim of dispersal.groups) { const group_row_fat : type_group_row_fat = { "user_id": user_id, "group_id": group_row_slim.group_id, }; await get_store_groups().create(group_row_fat); } } return Promise.resolve<_zeitbild.type_user_id>(user_id); } /** */ export async function update( user_id : _zeitbild.type_user_id, user_object : _zeitbild.type_user_object ) : Promise { const dispersal : type_dispersal = encode(user_object); // core { await get_store_core().update(user_id, dispersal.core); } // groups { const hits : Array<{key : int; preview : Record;}> = await get_store_groups().search( { "expression": "(user_id = $user_id)", "arguments": { "user_id": user_id, } } ); const contrast = lib_plankton.list.contrast( hits, hit => hit.preview.group_id.toFixed(0), dispersal.groups, group_row_slim => group_row_slim.group_id.toFixed(0) ); // delete { for (const entry of contrast.only_left) { await get_store_groups().delete(entry.left.key); } } // update { for (const entry of contrast.both) { const row_group_fat : type_group_row_fat = { "user_id": user_id, "group_id": entry.right.group_id, }; await get_store_groups().update(entry.left.key, row_group_fat); } } // create { for (const entry of contrast.only_right) { const row_group_fat : type_group_row_fat = { "user_id": user_id, "group_id": entry.right.group_id, }; await get_store_groups().create(row_group_fat); } } } return Promise.resolve(undefined); } /** */ export async function identify( name : string ) : Promise<_zeitbild.type_user_id> { const hits : Array<{key : _zeitbild.type_user_id; preview : /*type_preview*/Record;}> = await get_store_core().search( { "expression": "(name = $name)", "arguments": { "name": name, } } ); if (hits.length <= 0) { return Promise.reject<_zeitbild.type_user_id>(new Error("not found")); } else { return Promise.resolve<_zeitbild.type_user_id>(hits[0].key); } } }