Skip to content

Commit 98c9bb0

Browse files
committed
docu
1 parent ffd6b87 commit 98c9bb0

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

lib/services/storage/userStorage.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ import * as hasher from '../security/hash.js';
33
import { nanoid } from 'nanoid';
44
import SqliteConnection from './SqliteConnection.js';
55

6+
/**
7+
* Get all users.
8+
*
9+
* Notes:
10+
* - Password hashes are omitted by default to avoid leaking them to callers that don’t need them.
11+
* - numberOfJobs is computed via a subquery for each user.
12+
*
13+
* @param {boolean} withPassword - If true, include the hashed password in the returned objects; otherwise set password to null.
14+
* @returns {User[]} Array of users ordered by username.
15+
*/
616
export const getUsers = (withPassword) => {
717
const rows = SqliteConnection.query(
818
`SELECT u.id, u.username, u.password, u.last_login AS lastLogin, u.is_admin AS isAdmin,
@@ -17,6 +27,12 @@ export const getUsers = (withPassword) => {
1727
}));
1828
};
1929

30+
/**
31+
* Get a single user by id.
32+
*
33+
* @param {string} id - User id (primary key).
34+
* @returns {User|null} The user when found; otherwise null. The password field is included but callers should not expose it.
35+
*/
2036
export const getUser = (id) => {
2137
const rows = SqliteConnection.query(
2238
`SELECT u.id, u.username, u.password, u.last_login AS lastLogin, u.is_admin AS isAdmin,
@@ -31,6 +47,21 @@ export const getUser = (id) => {
3147
return { ...u, isAdmin: !!u.isAdmin };
3248
};
3349

50+
/**
51+
* Insert a new user or update an existing one.
52+
*
53+
* Behavior:
54+
* - When userId is provided and exists: updates username and isAdmin. Password is only updated when a non-empty password is provided.
55+
* - When userId is missing or does not exist: inserts a new user with a freshly generated id. last_login is initialized to null.
56+
* - Passwords are hashed using the same hashing function used for login comparison.
57+
*
58+
* @param {Object} params
59+
* @param {string} params.username - Username (must be unique in DB).
60+
* @param {string} [params.password] - Plain text password to set; if omitted on update, existing hash is preserved.
61+
* @param {string} [params.userId] - Existing user id to update; if missing, a new id is generated.
62+
* @param {boolean} params.isAdmin - Whether the user should have admin privileges.
63+
* @returns {void}
64+
*/
3465
export const upsertUser = ({ username, password, userId, isAdmin }) => {
3566
const id = userId || nanoid();
3667
// Check if user exists
@@ -64,18 +95,39 @@ export const upsertUser = ({ username, password, userId, isAdmin }) => {
6495
}
6596
};
6697

98+
/**
99+
* Update the last_login timestamp to now for the given user.
100+
*
101+
* @param {{userId: string}} params - Parameters.
102+
* @param {string} params.userId - The user's id.
103+
* @returns {void}
104+
*/
67105
export const setLastLoginToNow = ({ userId }) => {
68106
SqliteConnection.execute(`UPDATE users SET last_login = @now WHERE id = @id`, { id: userId, now: Date.now() });
69107
};
70108

109+
/**
110+
* Remove a user by id.
111+
*
112+
* Notes:
113+
* - In the SQLite schema, jobs reference users with ON DELETE CASCADE, so jobs (and their listings via jobs) are removed automatically.
114+
*
115+
* @param {string} userId - The id of the user to remove.
116+
* @returns {void}
117+
*/
71118
export const removeUser = (userId) => {
72119
SqliteConnection.execute(`DELETE FROM users WHERE id = @id`, { id: userId });
73120
};
74121

75122
/**
76123
* Ensure the demo user matches the demo mode setting.
124+
*
125+
* Behavior:
77126
* - When config.demoMode is false: remove the demo user (and its cascading data via FKs).
78127
* - When config.demoMode is true: ensure a 'demo' user exists with password 'demo' and admin rights.
128+
*
129+
* Security: The demo user's password is set to a known value ('demo') and should only be enabled in demoMode.
130+
* @returns {void}
79131
*/
80132
export const ensureDemoUserExists = () => {
81133
if (!config.demoMode) {
@@ -96,9 +148,13 @@ export const ensureDemoUserExists = () => {
96148

97149
/**
98150
* Ensure there is at least one administrator in the system.
151+
*
99152
* Behavior:
100153
* - If there are no users at all, create default 'admin' user with password 'admin'.
101154
* - If users exist but none is admin, promote the first existing user to admin.
155+
*
156+
* Security: On a fresh instance, a default admin/admin is created; change this password immediately.
157+
* @returns {void}
102158
*/
103159
export const ensureAdminUserExists = () => {
104160
const anyUser = SqliteConnection.query(`SELECT id FROM users LIMIT 1`).length > 0;

0 commit comments

Comments
 (0)