backend/source/repositories/user.ts

391 lines
7.2 KiB
TypeScript
Raw Normal View History

2025-09-25 17:18:16 +02:00
/*
This file is part of »zeitbild«.
Copyright 2025 'kcf' <fenris@folksprak.org>
»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 <http://www.gnu.org/licenses/>.
*/
2024-09-18 18:17:25 +02:00
namespace _zeitbild.repository.user
{
2025-10-17 13:16:56 +02:00
/**
*/
2025-10-23 11:34:00 +02:00
type type_core_row = {
2025-10-17 13:16:56 +02:00
name : string;
email_address : (null | string);
dav_token : (null | string);
};
2025-10-23 11:34:00 +02:00
/**
*/
type type_group_row_slim = {
group_id : int;
};
/**
*/
type type_group_row_fat = {
user_id : int;
group_id : int;
};
2025-10-17 13:16:56 +02:00
/**
*/
type type_preview = {
name : string;
};
2024-09-18 18:17:25 +02:00
/**
*/
2025-10-23 11:34:00 +02:00
type type_dispersal = {
core : type_core_row;
groups : Array<type_group_row_slim>;
};
/**
*/
var _store_core : (
2024-09-18 18:17:25 +02:00
null
|
lib_plankton.storage.type_store<
2024-09-21 11:05:24 +02:00
_zeitbild.type_user_id,
2025-10-23 11:34:00 +02:00
/*type_core_row*/Record<string, any>,
2024-09-18 18:17:25 +02:00
{},
lib_plankton.storage.type_sql_table_autokey_search_term,
2025-10-17 13:16:56 +02:00
/*type_preview*/Record<string, any>
2024-09-18 18:17:25 +02:00
>
) = null;
/**
*/
2025-10-23 11:34:00 +02:00
var _store_groups : (
null
|
lib_plankton.storage.type_store<
int,
/*type_group_row_fat*/Record<string, any>,
{},
lib_plankton.storage.type_sql_table_autokey_search_term,
Record<string, any>
>
) = null;
/**
*/
function get_store_core(
2025-10-17 13:16:56 +02:00
)
: lib_plankton.storage.type_store<
2024-09-21 11:05:24 +02:00
_zeitbild.type_user_id,
2025-10-23 11:34:00 +02:00
/*type_core_row*/Record<string, any>,
2024-09-18 18:17:25 +02:00
{},
lib_plankton.storage.type_sql_table_autokey_search_term,
2025-10-17 13:16:56 +02:00
/*type_preview*/Record<string, any>
2024-09-18 18:17:25 +02:00
>
{
2025-10-23 11:34:00 +02:00
if (_store_core === null)
2025-10-17 13:16:56 +02:00
{
2025-10-23 11:34:00 +02:00
_store_core = lib_plankton.storage.sql_table_autokey_store(
2024-09-18 18:17:25 +02:00
{
"database_implementation": _zeitbild.database.get_implementation(),
"table_name": "users",
"key_name": "id",
}
);
}
2025-10-17 13:16:56 +02:00
else
{
2024-09-18 18:17:25 +02:00
// do nothing
2025-10-23 11:34:00 +02:00
}
return _store_core;
}
/**
*/
function get_store_groups(
)
: lib_plankton.storage.type_store<
int,
/*type_group_row_fat*/Record<string, any>,
{},
lib_plankton.storage.type_sql_table_autokey_search_term,
Record<string, any>
>
{
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;
2024-09-18 18:17:25 +02:00
}
/**
*/
function encode(
2024-09-21 11:05:24 +02:00
user_object : _zeitbild.type_user_object
2025-10-17 13:16:56 +02:00
)
2025-10-23 11:34:00 +02:00
: type_dispersal
2024-09-18 18:17:25 +02:00
{
return {
2025-10-23 11:34:00 +02:00
"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,
}
)
)
),
2024-09-18 18:17:25 +02:00
};
}
/**
*/
function decode(
2025-10-23 11:34:00 +02:00
dispersal : type_dispersal
2025-10-17 13:16:56 +02:00
)
: _zeitbild.type_user_object
2024-09-18 18:17:25 +02:00
{
return {
2025-10-23 11:34:00 +02:00
"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,
2024-09-18 18:17:25 +02:00
};
}
/**
*/
export async function list(
2025-10-17 13:16:56 +02:00
)
: Promise<
Array<
{
id : _zeitbild.type_user_id;
name : string;
}
>
>
{
2025-10-23 11:34:00 +02:00
const hits : Array<{key : int; preview : /*type_preview*/Record<string, any>;}> = await get_store_core().search(
{
"expression": "TRUE",
"arguments": {}
}
);
return Promise.resolve(
hits
.map(
(hit) => ({
"id": hit.key,
"name": hit.preview.name,
})
)
);
}
2024-09-18 18:17:25 +02:00
/**
*/
export async function read(
2024-09-21 11:05:24 +02:00
user_id : _zeitbild.type_user_id
2025-10-17 13:16:56 +02:00
)
: Promise<_zeitbild.type_user_object>
2024-09-18 18:17:25 +02:00
{
2025-10-23 11:34:00 +02:00
const core_row : type_core_row = ((await get_store_core().read(user_id)) as type_core_row);
const group_rows : Array<type_group_row_fat> = (
(
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);
2024-09-21 11:05:24 +02:00
return Promise.resolve<_zeitbild.type_user_object>(user_object);
2024-09-18 18:17:25 +02:00
}
/**
*/
export async function create(
2024-09-21 11:05:24 +02:00
user_object : _zeitbild.type_user_object
2025-10-17 13:16:56 +02:00
)
: Promise<_zeitbild.type_user_id>
2024-09-18 18:17:25 +02:00
{
2025-10-23 11:34:00 +02:00
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);
}
}
2024-09-21 11:05:24 +02:00
return Promise.resolve<_zeitbild.type_user_id>(user_id);
2024-09-18 18:17:25 +02:00
}
/**
*/
export async function update(
user_id : _zeitbild.type_user_id,
user_object : _zeitbild.type_user_object
2025-10-17 13:16:56 +02:00
)
: Promise<void>
{
2025-10-23 11:34:00 +02:00
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<string, any>;}> = 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<void>(undefined);
}
2024-09-18 18:17:25 +02:00
/**
*/
export async function identify(
name : string
2025-10-17 13:16:56 +02:00
)
: Promise<_zeitbild.type_user_id>
2024-09-18 18:17:25 +02:00
{
2025-10-23 11:34:00 +02:00
const hits : Array<{key : _zeitbild.type_user_id; preview : /*type_preview*/Record<string, any>;}> = await get_store_core().search(
2024-09-18 18:17:25 +02:00
{
"expression": "(name = $name)",
"arguments": {
"name": name,
}
}
);
2025-10-17 13:16:56 +02:00
if (hits.length <= 0)
{
2024-09-21 11:05:24 +02:00
return Promise.reject<_zeitbild.type_user_id>(new Error("not found"));
2024-09-18 18:17:25 +02:00
}
2025-10-17 13:16:56 +02:00
else
{
2024-09-21 11:05:24 +02:00
return Promise.resolve<_zeitbild.type_user_id>(hits[0].key);
2024-09-18 18:17:25 +02:00
}
}
}