@kollors/deep-json-server 1.0.0-alpha.7 → 1.0.0-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -11
- package/README.ru.md +40 -11
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/src/auth/contract.d.ts +3 -0
- package/dist/src/auth/contract.js +8 -1
- package/dist/src/auth/contract.js.map +1 -1
- package/dist/src/auth/input.d.ts +18 -0
- package/dist/src/auth/input.js +34 -0
- package/dist/src/auth/input.js.map +1 -0
- package/dist/src/auth/password.d.ts +4 -0
- package/dist/src/auth/password.js +5 -1
- package/dist/src/auth/password.js.map +1 -1
- package/dist/src/auth/routes.d.ts +1 -1
- package/dist/src/auth/routes.js +4 -1
- package/dist/src/auth/routes.js.map +1 -1
- package/dist/src/auth/service.d.ts +48 -9
- package/dist/src/auth/service.js +143 -68
- package/dist/src/auth/service.js.map +1 -1
- package/dist/src/auth/store.d.ts +26 -0
- package/dist/src/auth/store.js +82 -0
- package/dist/src/auth/store.js.map +1 -0
- package/dist/src/cli/index.js +6 -8
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/core/config-values.d.ts +28 -0
- package/dist/src/core/config-values.js +53 -0
- package/dist/src/core/config-values.js.map +1 -0
- package/dist/src/core/constants.d.ts +1 -1
- package/dist/src/core/constants.js +1 -1
- package/dist/src/core/database.d.ts +4 -1
- package/dist/src/core/database.js +2 -2
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/core/engine.d.ts +3 -2
- package/dist/src/core/engine.js +53 -44
- package/dist/src/core/engine.js.map +1 -1
- package/dist/src/core/lifecycle/mutation.d.ts +3 -3
- package/dist/src/core/lifecycle/mutation.js +2 -2
- package/dist/src/core/lifecycle/mutation.js.map +1 -1
- package/dist/src/core/lifecycle/options.d.ts +1 -0
- package/dist/src/core/lifecycle/options.js +2 -4
- package/dist/src/core/lifecycle/options.js.map +1 -1
- package/dist/src/core/model.d.ts +2 -1
- package/dist/src/core/model.js.map +1 -1
- package/dist/src/core/mutations/write.d.ts +1 -2
- package/dist/src/core/mutations/write.js.map +1 -1
- package/dist/src/core/operations.d.ts +33 -0
- package/dist/src/core/operations.js +10 -0
- package/dist/src/core/operations.js.map +1 -0
- package/dist/src/core/pagination.d.ts +2 -2
- package/dist/src/core/pagination.js +3 -5
- package/dist/src/core/pagination.js.map +1 -1
- package/dist/src/core/paths.d.ts +2 -2
- package/dist/src/core/paths.js +6 -2
- package/dist/src/core/paths.js.map +1 -1
- package/dist/src/files/disk-store.js +3 -20
- package/dist/src/files/disk-store.js.map +1 -1
- package/dist/src/files/memory-store.js +13 -13
- package/dist/src/files/memory-store.js.map +1 -1
- package/dist/src/files/streams.d.ts +5 -0
- package/dist/src/files/streams.js +20 -0
- package/dist/src/files/streams.js.map +1 -0
- package/dist/src/graphql/entry.d.ts +11 -2
- package/dist/src/graphql/entry.js +12 -2
- package/dist/src/graphql/entry.js.map +1 -1
- package/dist/src/graphql/{public.js → generate.js} +1 -1
- package/dist/src/graphql/generate.js.map +1 -0
- package/dist/src/graphql/resolvers.js +1 -1
- package/dist/src/graphql/resolvers.js.map +1 -1
- package/dist/src/graphql/schema.js +6 -3
- package/dist/src/graphql/schema.js.map +1 -1
- package/dist/src/openapi/auth.d.ts +2 -2
- package/dist/src/openapi/auth.js +82 -15
- package/dist/src/openapi/auth.js.map +1 -1
- package/dist/src/openapi/document.js +16 -13
- package/dist/src/openapi/document.js.map +1 -1
- package/dist/src/openapi/entry.d.ts +12 -1
- package/dist/src/openapi/entry.js +12 -1
- package/dist/src/openapi/entry.js.map +1 -1
- package/dist/src/openapi/{public.d.ts → generate.d.ts} +9 -16
- package/dist/src/openapi/generate.js +39 -0
- package/dist/src/openapi/generate.js.map +1 -0
- package/dist/src/openapi/options.d.ts +20 -0
- package/dist/src/openapi/options.js +13 -0
- package/dist/src/openapi/options.js.map +1 -0
- package/dist/src/openapi/write.d.ts +5 -0
- package/dist/src/openapi/write.js +12 -0
- package/dist/src/openapi/write.js.map +1 -0
- package/dist/src/rest/routes.js +6 -9
- package/dist/src/rest/routes.js.map +1 -1
- package/dist/src/server/config.d.ts +5 -8
- package/dist/src/server/config.js +19 -60
- package/dist/src/server/config.js.map +1 -1
- package/dist/src/server/create.js +6 -9
- package/dist/src/server/create.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/graphql/lazy.d.ts +0 -10
- package/dist/src/graphql/lazy.js +0 -13
- package/dist/src/graphql/lazy.js.map +0 -1
- package/dist/src/graphql/public.js.map +0 -1
- package/dist/src/openapi/index.d.ts +0 -13
- package/dist/src/openapi/index.js +0 -37
- package/dist/src/openapi/index.js.map +0 -1
- package/dist/src/openapi/lazy.d.ts +0 -11
- package/dist/src/openapi/lazy.js +0 -13
- package/dist/src/openapi/lazy.js.map +0 -1
- package/dist/src/openapi/public.js +0 -26
- package/dist/src/openapi/public.js.map +0 -1
- /package/dist/src/graphql/{public.d.ts → generate.d.ts} +0 -0
package/dist/src/auth/service.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
-
import { readFile } from 'node:fs/promises';
|
|
3
2
|
import { domainError } from '../core/errors.js';
|
|
4
|
-
import {
|
|
5
|
-
import { DEFAULT_SESSION_SECONDS
|
|
6
|
-
import {
|
|
3
|
+
import { createUniqueId } from '../core/utils.js';
|
|
4
|
+
import { DEFAULT_SESSION_SECONDS } from './contract.js';
|
|
5
|
+
import { adminChange, credentials, passwordChange } from './input.js';
|
|
6
|
+
import { DUMMY_HASH, hashPassword, verifyPassword } from './password.js';
|
|
7
|
+
import { createAuthStore } from './store.js';
|
|
7
8
|
/** Создаёт исключение отсутствия действительной сессии без раскрытия причины отказа.
|
|
8
9
|
* @example unauthorized() → Error с code = 'UNAUTHENTICATED'.
|
|
9
10
|
*/
|
|
@@ -12,63 +13,95 @@ const unauthorized = () => domainError('UNAUTHENTICATED', 'Invalid credentials o
|
|
|
12
13
|
* @example tokenKey('abc') → 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'.
|
|
13
14
|
*/
|
|
14
15
|
const tokenKey = (token) => createHash('sha256').update(token).digest('hex');
|
|
15
|
-
/** Возвращает публичные поля пользователя в новом
|
|
16
|
-
* @example
|
|
16
|
+
/** Возвращает публичные поля пользователя в новом объекте.
|
|
17
|
+
* @example { id: '1', username: 'anna', isAdmin: false, passwordHash: '…' } → { id: '1', username: 'anna', isAdmin: false }.
|
|
17
18
|
*/
|
|
18
|
-
const publicUser = (user) => ({ id: user.id, username: user.username, isAdmin: user.isAdmin
|
|
19
|
+
const publicUser = (user) => ({ id: user.id, username: user.username, isAdmin: user.isAdmin });
|
|
19
20
|
export class AuthService {
|
|
20
|
-
|
|
21
|
+
store;
|
|
21
22
|
expiresIn;
|
|
22
23
|
sessions = new Map();
|
|
23
|
-
|
|
24
|
+
pendingPasswords = 0;
|
|
24
25
|
closed = false;
|
|
25
|
-
constructor(
|
|
26
|
-
this.
|
|
26
|
+
constructor(store, expiresIn) {
|
|
27
|
+
this.store = store;
|
|
27
28
|
this.expiresIn = expiresIn;
|
|
28
29
|
}
|
|
29
|
-
/** Проверяет
|
|
30
|
+
/** Проверяет пароль и создаёт сессию с актуальными правами пользователя.
|
|
30
31
|
* @example Корректные username и password → { accessToken, expiresIn, user }; неверный пароль → исключение.
|
|
31
32
|
*/
|
|
32
33
|
async login(body) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
body.password.length > MAX_PASSWORD_LENGTH)
|
|
41
|
-
throw domainError('INVALID_INPUT', 'Supply username and password');
|
|
42
|
-
if (this.closed)
|
|
43
|
-
throw unauthorized();
|
|
44
|
-
if (this.pendingLogins >= 4)
|
|
45
|
-
throw domainError('TOO_MANY_REQUESTS', 'Too many simultaneous login attempts');
|
|
46
|
-
this.pendingLogins++;
|
|
47
|
-
let user;
|
|
48
|
-
let valid;
|
|
49
|
-
try {
|
|
50
|
-
user = this.users.get(body.username);
|
|
51
|
-
valid = await verifyPassword(body.password, user?.passwordHash ?? DUMMY_HASH);
|
|
52
|
-
}
|
|
53
|
-
finally {
|
|
54
|
-
this.pendingLogins--;
|
|
55
|
-
}
|
|
56
|
-
if (!user || !valid || this.closed)
|
|
34
|
+
const { username, password } = credentials(body);
|
|
35
|
+
const user = this.store.read().byUsername.get(username);
|
|
36
|
+
const valid = await this.passwordWork(() => verifyPassword(password, user?.passwordHash ?? DUMMY_HASH));
|
|
37
|
+
this.assertOpen();
|
|
38
|
+
const current = user && this.store.read().byId.get(user.id);
|
|
39
|
+
// Смена пароля во время scrypt не должна выдавать новую сессию по прежнему паролю.
|
|
40
|
+
if (!user || !valid || !current || current.passwordHash !== user.passwordHash)
|
|
57
41
|
throw unauthorized();
|
|
58
42
|
this.prune();
|
|
59
43
|
if (this.sessions.size >= 10000)
|
|
60
44
|
throw domainError('TOO_MANY_REQUESTS', 'Session limit reached');
|
|
61
45
|
const accessToken = randomBytes(32).toString('base64url');
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
46
|
+
this.sessions.set(tokenKey(accessToken), { userId: current.id, expiresAt: Date.now() + this.expiresIn * 1000 });
|
|
47
|
+
return { accessToken, expiresIn: this.expiresIn, user: publicUser(current) };
|
|
48
|
+
}
|
|
49
|
+
/** Создаёт обычного пользователя с новым идентификатором и хешем пароля, не открывая сессию.
|
|
50
|
+
* @example { username: 'anna', password: 'secret' } → { id: '…', username: 'anna', isAdmin: false }.
|
|
51
|
+
*/
|
|
52
|
+
async register(body) {
|
|
53
|
+
const { username, password } = credentials(body);
|
|
54
|
+
const passwordHash = await this.passwordWork(() => hashPassword(password));
|
|
55
|
+
const user = await this.store.update((users) => {
|
|
56
|
+
this.assertOpen();
|
|
57
|
+
return { id: createUniqueId((id) => users.byId.has(id)), username, passwordHash, isAdmin: false };
|
|
58
|
+
});
|
|
59
|
+
return publicUser(user);
|
|
60
|
+
}
|
|
61
|
+
/** Меняет свой пароль после проверки текущего либо пароль обычного пользователя по правам администратора.
|
|
62
|
+
* @example Свой id и два пароля → { success: true } с завершением всех своих сессий; чужой администратор → FORBIDDEN.
|
|
63
|
+
*/
|
|
64
|
+
async changePassword(authorization, id, body) {
|
|
65
|
+
const { actor, target } = this.passwordTarget(this.store.read(), authorization, id);
|
|
66
|
+
const { newPassword, currentPassword } = passwordChange(body);
|
|
67
|
+
const own = actor.id === target.id;
|
|
68
|
+
if (own && currentPassword === undefined)
|
|
69
|
+
throw domainError('INVALID_INPUT', 'Supply currentPassword to change your own password');
|
|
70
|
+
const passwordHash = await this.passwordWork(async () => {
|
|
71
|
+
if (own && !(await verifyPassword(currentPassword, target.passwordHash)))
|
|
72
|
+
throw unauthorized();
|
|
73
|
+
return hashPassword(newPassword);
|
|
74
|
+
});
|
|
75
|
+
await this.store.update((users) => {
|
|
76
|
+
const { target: current } = this.passwordTarget(users, authorization, id);
|
|
77
|
+
if (current.passwordHash !== target.passwordHash)
|
|
78
|
+
throw domainError('CONFLICT', 'Password changed during the request');
|
|
79
|
+
return { ...current, passwordHash };
|
|
80
|
+
}, () => this.revoke(id));
|
|
81
|
+
return { success: true };
|
|
65
82
|
}
|
|
66
|
-
/**
|
|
67
|
-
* @example
|
|
83
|
+
/** Меняет статус по правам действующего администратора и сохраняет хотя бы одного при отказе от собственных прав.
|
|
84
|
+
* @example Последний администратор и { isAdmin: false } для себя → CONFLICT; назначение другого → обновлённый пользователь.
|
|
85
|
+
*/
|
|
86
|
+
async changeAdmin(authorization, id, body) {
|
|
87
|
+
this.requireAdmin(authorization);
|
|
88
|
+
const isAdmin = adminChange(body);
|
|
89
|
+
const user = await this.store.update((users) => {
|
|
90
|
+
const actor = this.requireAdmin(authorization);
|
|
91
|
+
const target = users.byId.get(id);
|
|
92
|
+
if (!target)
|
|
93
|
+
throw domainError('NOT_FOUND', 'Auth user not found');
|
|
94
|
+
if (!isAdmin && actor.id === target.id && ![...users.byId.values()].some((user) => user.id !== id && user.isAdmin))
|
|
95
|
+
throw domainError('CONFLICT', 'The last administrator cannot remove their own admin status');
|
|
96
|
+
return { ...target, isAdmin };
|
|
97
|
+
});
|
|
98
|
+
return publicUser(user);
|
|
99
|
+
}
|
|
100
|
+
/** Проверяет токен и возвращает копию пользователя с текущими правами.
|
|
101
|
+
* @example После снятия статуса прежний токен возвращает isAdmin: false без повторного входа.
|
|
68
102
|
*/
|
|
69
103
|
me(authorization) {
|
|
70
|
-
|
|
71
|
-
return publicUser(session.user);
|
|
104
|
+
return publicUser(this.identity(authorization));
|
|
72
105
|
}
|
|
73
106
|
/** Проверяет токен и удаляет соответствующую сессию.
|
|
74
107
|
* @example Действительный токен → { success: true }; повторный выход с ним → ошибка.
|
|
@@ -78,18 +111,40 @@ export class AuthService {
|
|
|
78
111
|
this.sessions.delete(key);
|
|
79
112
|
return { success: true };
|
|
80
113
|
}
|
|
81
|
-
/** Запрещает новые
|
|
114
|
+
/** Запрещает новые обращения и очищает сессии в памяти.
|
|
82
115
|
* @example close() → undefined; последующий login() → отказ.
|
|
83
116
|
*/
|
|
84
117
|
close() {
|
|
85
118
|
this.closed = true;
|
|
86
119
|
this.sessions.clear();
|
|
87
|
-
|
|
120
|
+
}
|
|
121
|
+
/** Ограничивает число одновременных вычислений хешей и освобождает место даже при ошибке.
|
|
122
|
+
* @example Четыре незавершённых вычисления → пятое получает TOO_MANY_REQUESTS.
|
|
123
|
+
*/
|
|
124
|
+
async passwordWork(operation) {
|
|
125
|
+
this.assertOpen();
|
|
126
|
+
if (this.pendingPasswords >= 4)
|
|
127
|
+
throw domainError('TOO_MANY_REQUESTS', 'Too many simultaneous password operations');
|
|
128
|
+
this.pendingPasswords++;
|
|
129
|
+
try {
|
|
130
|
+
return await operation();
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
this.pendingPasswords--;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Отклоняет обращения после закрытия сервиса.
|
|
137
|
+
* @example closed = true → UNAUTHENTICATED; false → undefined.
|
|
138
|
+
*/
|
|
139
|
+
assertOpen() {
|
|
140
|
+
if (this.closed)
|
|
141
|
+
throw unauthorized();
|
|
88
142
|
}
|
|
89
143
|
/** Находит сессию по хешу токена и проверяет срок; просроченную сессию удаляет.
|
|
90
144
|
* @example Действительный Bearer-токен → [ключ, сессия]; отсутствующий или истёкший → ошибка.
|
|
91
145
|
*/
|
|
92
146
|
session(authorization) {
|
|
147
|
+
this.assertOpen();
|
|
93
148
|
if (typeof authorization !== 'string')
|
|
94
149
|
throw unauthorized();
|
|
95
150
|
const match = /^Bearer ([A-Za-z0-9_-]{43})$/i.exec(authorization);
|
|
@@ -103,6 +158,47 @@ export class AuthService {
|
|
|
103
158
|
}
|
|
104
159
|
return [key, session];
|
|
105
160
|
}
|
|
161
|
+
/** Получает текущую запись по идентификатору из проверенной сессии.
|
|
162
|
+
* @example Сессия с userId = '1' → актуальная запись с id = '1'; отсутствующая запись → ошибка.
|
|
163
|
+
*/
|
|
164
|
+
identity(authorization) {
|
|
165
|
+
const [, session] = this.session(authorization);
|
|
166
|
+
const user = this.store.read().byId.get(session.userId);
|
|
167
|
+
if (!user)
|
|
168
|
+
throw unauthorized();
|
|
169
|
+
return user;
|
|
170
|
+
}
|
|
171
|
+
/** Проверяет текущие права администратора.
|
|
172
|
+
* @example Действующая сессия обычного пользователя → FORBIDDEN; администратора → его запись.
|
|
173
|
+
*/
|
|
174
|
+
requireAdmin(authorization) {
|
|
175
|
+
const user = this.identity(authorization);
|
|
176
|
+
if (!user.isAdmin)
|
|
177
|
+
throw domainError('FORBIDDEN', 'Administrator access required');
|
|
178
|
+
return user;
|
|
179
|
+
}
|
|
180
|
+
/** Проверяет владельца пароля и запрет изменения пароля другого администратора.
|
|
181
|
+
* @example Администратор и обычная чужая запись → { actor, target }; два разных администратора → FORBIDDEN.
|
|
182
|
+
*/
|
|
183
|
+
passwordTarget(users, authorization, id) {
|
|
184
|
+
const actor = this.identity(authorization);
|
|
185
|
+
if (actor.id !== id && !actor.isAdmin)
|
|
186
|
+
throw domainError('FORBIDDEN', 'You can only change your own password');
|
|
187
|
+
const target = users.byId.get(id);
|
|
188
|
+
if (!target)
|
|
189
|
+
throw domainError('NOT_FOUND', 'Auth user not found');
|
|
190
|
+
if (actor.id !== id && target.isAdmin)
|
|
191
|
+
throw domainError('FORBIDDEN', 'Cannot change another administrator password');
|
|
192
|
+
return { actor, target };
|
|
193
|
+
}
|
|
194
|
+
/** Завершает все сессии одного пользователя после сохранения нового пароля.
|
|
195
|
+
* @example Две сессии id = '1' и одна id = '2' → остаётся сессия id = '2'.
|
|
196
|
+
*/
|
|
197
|
+
revoke(id) {
|
|
198
|
+
for (const [key, session] of this.sessions)
|
|
199
|
+
if (session.userId === id)
|
|
200
|
+
this.sessions.delete(key);
|
|
201
|
+
}
|
|
106
202
|
/** Удаляет из памяти сессии, срок которых истёк к текущему моменту.
|
|
107
203
|
* @example Одна истёкшая и одна действующая сессия → остаётся одна действующая; результат undefined.
|
|
108
204
|
*/
|
|
@@ -113,31 +209,10 @@ export class AuthService {
|
|
|
113
209
|
this.sessions.delete(key);
|
|
114
210
|
}
|
|
115
211
|
}
|
|
116
|
-
/**
|
|
212
|
+
/** Открывает источник учётных записей и создаёт хранилище сессий в памяти.
|
|
117
213
|
* @example createAuthService({ users: [] }) → Promise<AuthService>; повторяющиеся id → ошибка.
|
|
118
214
|
*/
|
|
119
215
|
export async function createAuthService(config) {
|
|
120
|
-
|
|
121
|
-
if (!Array.isArray(records))
|
|
122
|
-
throw new Error('Auth users must be an array');
|
|
123
|
-
const users = new Map();
|
|
124
|
-
const ids = new Set();
|
|
125
|
-
for (const record of records) {
|
|
126
|
-
if (!isObject(record) ||
|
|
127
|
-
!hasOnlyKeys(record, ['id', 'username', 'passwordHash', 'isAdmin']) ||
|
|
128
|
-
typeof record.id !== 'string' ||
|
|
129
|
-
!record.id.trim() ||
|
|
130
|
-
typeof record.username !== 'string' ||
|
|
131
|
-
!record.username.trim() ||
|
|
132
|
-
record.username.length > MAX_USERNAME_LENGTH ||
|
|
133
|
-
!validPasswordHash(record.passwordHash) ||
|
|
134
|
-
(record.isAdmin !== undefined && typeof record.isAdmin !== 'boolean'))
|
|
135
|
-
throw new Error('Auth users require id, username and a valid passwordHash');
|
|
136
|
-
if (ids.has(record.id) || users.has(record.username))
|
|
137
|
-
throw new Error('Auth user ids and usernames must be unique');
|
|
138
|
-
ids.add(record.id);
|
|
139
|
-
users.set(record.username, { id: record.id, username: record.username, passwordHash: record.passwordHash, isAdmin: record.isAdmin ?? false });
|
|
140
|
-
}
|
|
141
|
-
return new AuthService(users, config.expiresIn ?? DEFAULT_SESSION_SECONDS);
|
|
216
|
+
return new AuthService(await createAuthStore(config.users), config.expiresIn ?? DEFAULT_SESSION_SECONDS);
|
|
142
217
|
}
|
|
143
218
|
//# sourceMappingURL=service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/auth/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/auth/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { JSONFile } from 'lowdb/node';
|
|
2
|
+
import { type AuthConfig, type AuthUserRecord } from './contract.js';
|
|
3
|
+
export type StoredUser = Readonly<Required<AuthUserRecord>>;
|
|
4
|
+
export interface UserIndex {
|
|
5
|
+
byId: ReadonlyMap<string, StoredUser>;
|
|
6
|
+
byUsername: ReadonlyMap<string, StoredUser>;
|
|
7
|
+
}
|
|
8
|
+
/** Хранит подтверждённые записи и последовательно сохраняет изменения одного пользователя. */
|
|
9
|
+
export declare class AuthStore {
|
|
10
|
+
private users;
|
|
11
|
+
private file?;
|
|
12
|
+
private schedule;
|
|
13
|
+
constructor(users: UserIndex, file?: JSONFile<StoredUser[]> | undefined);
|
|
14
|
+
/** Возвращает индексы последнего успешно сохранённого состояния.
|
|
15
|
+
* @example Во время записи нового пароля read() ещё возвращает запись с прежним хешем.
|
|
16
|
+
*/
|
|
17
|
+
read(): UserIndex;
|
|
18
|
+
/** Проверяет изменение внутри очереди и публикует его после записи; обработчик подтверждения вызывается синхронно.
|
|
19
|
+
* @example Успешная запись → новый пользователь; ошибка файла → прежние индексы, обработчик не вызван.
|
|
20
|
+
*/
|
|
21
|
+
update(operation: (users: UserIndex) => StoredUser, committed?: () => void): Promise<StoredUser>;
|
|
22
|
+
}
|
|
23
|
+
/** Загружает массив из файла или памяти и подключает запись в тот же источник.
|
|
24
|
+
* @example Массив → хранилище в памяти; 'users.json' → чтение и сохранение JSON-массива через JSONFile.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createAuthStore(source: AuthConfig['users']): Promise<AuthStore>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { JSONFile } from 'lowdb/node';
|
|
2
|
+
import { domainError } from '../core/errors.js';
|
|
3
|
+
import { createSerialQueue, hasOnlyKeys, isObject } from '../core/utils.js';
|
|
4
|
+
import { MAX_USERNAME_LENGTH } from './contract.js';
|
|
5
|
+
import { validPasswordHash } from './password.js';
|
|
6
|
+
/** Проверяет записи и строит индексы по двум уникальным строковым ключам.
|
|
7
|
+
* @example Две записи с разными id и username → два индекса; повторяющийся ключ → ошибка.
|
|
8
|
+
*/
|
|
9
|
+
function indexUsers(records) {
|
|
10
|
+
if (!Array.isArray(records))
|
|
11
|
+
throw new Error('Auth users must be an array');
|
|
12
|
+
const byId = new Map();
|
|
13
|
+
const byUsername = new Map();
|
|
14
|
+
for (const record of records) {
|
|
15
|
+
if (!isObject(record) ||
|
|
16
|
+
!hasOnlyKeys(record, ['id', 'username', 'passwordHash', 'isAdmin']) ||
|
|
17
|
+
typeof record.id !== 'string' ||
|
|
18
|
+
!record.id.trim() ||
|
|
19
|
+
typeof record.username !== 'string' ||
|
|
20
|
+
!record.username.trim() ||
|
|
21
|
+
record.username.length > MAX_USERNAME_LENGTH ||
|
|
22
|
+
!validPasswordHash(record.passwordHash) ||
|
|
23
|
+
(record.isAdmin !== undefined && typeof record.isAdmin !== 'boolean'))
|
|
24
|
+
throw new Error('Auth users require id, username and a valid passwordHash');
|
|
25
|
+
if (byId.has(record.id) || byUsername.has(record.username))
|
|
26
|
+
throw new Error('Auth user ids and usernames must be unique');
|
|
27
|
+
const user = Object.freeze({ id: record.id, username: record.username, passwordHash: record.passwordHash, isAdmin: record.isAdmin ?? false });
|
|
28
|
+
byId.set(user.id, user);
|
|
29
|
+
byUsername.set(user.username, user);
|
|
30
|
+
}
|
|
31
|
+
return { byId, byUsername };
|
|
32
|
+
}
|
|
33
|
+
/** Хранит подтверждённые записи и последовательно сохраняет изменения одного пользователя. */
|
|
34
|
+
export class AuthStore {
|
|
35
|
+
users;
|
|
36
|
+
file;
|
|
37
|
+
schedule = createSerialQueue();
|
|
38
|
+
constructor(users, file) {
|
|
39
|
+
this.users = users;
|
|
40
|
+
this.file = file;
|
|
41
|
+
}
|
|
42
|
+
/** Возвращает индексы последнего успешно сохранённого состояния.
|
|
43
|
+
* @example Во время записи нового пароля read() ещё возвращает запись с прежним хешем.
|
|
44
|
+
*/
|
|
45
|
+
read() {
|
|
46
|
+
return this.users;
|
|
47
|
+
}
|
|
48
|
+
/** Проверяет изменение внутри очереди и публикует его после записи; обработчик подтверждения вызывается синхронно.
|
|
49
|
+
* @example Успешная запись → новый пользователь; ошибка файла → прежние индексы, обработчик не вызван.
|
|
50
|
+
*/
|
|
51
|
+
update(operation, committed) {
|
|
52
|
+
return this.schedule(async () => {
|
|
53
|
+
const user = Object.freeze(operation(this.users));
|
|
54
|
+
const owner = this.users.byUsername.get(user.username);
|
|
55
|
+
if (owner && owner.id !== user.id)
|
|
56
|
+
throw domainError('CONFLICT', 'Username already exists');
|
|
57
|
+
const byId = new Map(this.users.byId);
|
|
58
|
+
const byUsername = new Map(this.users.byUsername);
|
|
59
|
+
const previous = byId.get(user.id);
|
|
60
|
+
if (previous)
|
|
61
|
+
byUsername.delete(previous.username);
|
|
62
|
+
byId.set(user.id, user);
|
|
63
|
+
byUsername.set(user.username, user);
|
|
64
|
+
if (this.file)
|
|
65
|
+
await this.file.write([...byId.values()]);
|
|
66
|
+
this.users = { byId, byUsername };
|
|
67
|
+
committed?.();
|
|
68
|
+
return user;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Загружает массив из файла или памяти и подключает запись в тот же источник.
|
|
73
|
+
* @example Массив → хранилище в памяти; 'users.json' → чтение и сохранение JSON-массива через JSONFile.
|
|
74
|
+
*/
|
|
75
|
+
export async function createAuthStore(source) {
|
|
76
|
+
const file = typeof source === 'string' ? new JSONFile(source) : undefined;
|
|
77
|
+
const records = file ? await file.read() : source;
|
|
78
|
+
if (file && records === null)
|
|
79
|
+
throw new Error(`Auth users file not found: ${source}`);
|
|
80
|
+
return new AuthStore(indexUsers(records), file);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/auth/store.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import process from 'node:process';
|
|
|
2
2
|
import { DEFAULT_HOST, DEFAULT_PORT, VERSION } from '../core/constants.js';
|
|
3
3
|
import { inputPaths, validateExportPaths } from '../core/paths.js';
|
|
4
4
|
import { isObject } from '../core/utils.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { writeGraphql } from '../graphql/entry.js';
|
|
6
|
+
import { writeOpenapi } from '../openapi/entry.js';
|
|
7
7
|
import { configure, configureGeneration, readConfigModule } from '../server/config.js';
|
|
8
8
|
import { createConfiguredServer } from '../server/create.js';
|
|
9
9
|
import { resolveFeatures } from '../server/features.js';
|
|
@@ -103,12 +103,12 @@ export async function runCli(args = process.argv.slice(2), services = { createSe
|
|
|
103
103
|
return path;
|
|
104
104
|
});
|
|
105
105
|
await validateExportPaths(destinations, inputPaths(source.config, source.directory, source.path));
|
|
106
|
+
const { loadModel } = await import('../core/model.js');
|
|
107
|
+
const model = await loadModel(config.database.schema, { auth: config.auth != null, timestamps: config.database.timestamps, softDelete: config.database.softDelete });
|
|
106
108
|
const openapi = formats.includes('openapi')
|
|
107
|
-
? await
|
|
109
|
+
? (await import('../openapi/generate.js')).openapiFromModel(model, {
|
|
108
110
|
files: config.files != null,
|
|
109
111
|
auth: config.auth != null,
|
|
110
|
-
timestamps: config.database.timestamps,
|
|
111
|
-
softDelete: config.database.softDelete,
|
|
112
112
|
host: config.server.host,
|
|
113
113
|
port: config.server.port,
|
|
114
114
|
pageSize: config.server.pageSize,
|
|
@@ -116,9 +116,7 @@ export async function runCli(args = process.argv.slice(2), services = { createSe
|
|
|
116
116
|
info: config.openapi.info,
|
|
117
117
|
})
|
|
118
118
|
: undefined;
|
|
119
|
-
const graphql = formats.includes('graphql')
|
|
120
|
-
? await generateGraphql(config.database.schema, { auth: config.auth != null, timestamps: config.database.timestamps, softDelete: config.database.softDelete })
|
|
121
|
-
: undefined;
|
|
119
|
+
const graphql = formats.includes('graphql') ? (await import('../graphql/generate.js')).graphqlFromModel(model) : undefined;
|
|
122
120
|
if (openapi) {
|
|
123
121
|
await writeOpenapi(openapi, config.openapi.path);
|
|
124
122
|
process.stdout.write(`OpenAPI: ${config.openapi.path}\n`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Проверяет объект и обязательность значения; необязательные null и undefined пропускает.
|
|
2
|
+
* @example getObject(undefined, 'data') → undefined; getObject([], 'data', true) → ошибка.
|
|
3
|
+
*/
|
|
4
|
+
export declare function getObject(value: unknown, path: string, required: true): Record<string, unknown>;
|
|
5
|
+
export declare function getObject(value: unknown, path: string, required?: false): Record<string, unknown> | undefined;
|
|
6
|
+
/** Проверяет непустую строку, не обрезая её; необязательные null и undefined пропускает.
|
|
7
|
+
* @example getString(' a ', 'name') → ' a '; getString('', 'name') → ошибка.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getString(value: unknown, path: string, required: true): string;
|
|
10
|
+
export declare function getString(value: unknown, path: string, required?: false): string | undefined;
|
|
11
|
+
/** Принимает положительное безопасное целое число или отсутствие значения.
|
|
12
|
+
* @example getPositiveInteger(2, 'size') → 2; getPositiveInteger(0, 'size') → ошибка.
|
|
13
|
+
*/
|
|
14
|
+
export declare const getPositiveInteger: (value: unknown, path: string) => number | undefined;
|
|
15
|
+
/** Проверяет необязательный логический флаг, не преобразуя строки в boolean.
|
|
16
|
+
* @example getBoolean(false, 'flag') → false; getBoolean('false', 'flag') → ошибка.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getBoolean(value: unknown, path: string): boolean | undefined;
|
|
19
|
+
/** Проверяет адрес и порт и подставляет значения по умолчанию.
|
|
20
|
+
* @example normalizeAddress({ port: 0 }) → { host: '127.0.0.1', port: 0 }.
|
|
21
|
+
*/
|
|
22
|
+
export declare function normalizeAddress(options: {
|
|
23
|
+
host?: unknown;
|
|
24
|
+
port?: unknown;
|
|
25
|
+
}): {
|
|
26
|
+
host: string;
|
|
27
|
+
port: number;
|
|
28
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { DEFAULT_HOST, DEFAULT_PORT } from './constants.js';
|
|
2
|
+
import { isObject, isPortNumber } from './utils.js';
|
|
3
|
+
export function getObject(value, path, required = false) {
|
|
4
|
+
if (value == null && !required) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
if (!isObject(value)) {
|
|
8
|
+
throw new Error(`Ключ ${path} должен быть JSON-объектом`);
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
export function getString(value, path, required = false) {
|
|
13
|
+
if (value == null && !required) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
17
|
+
throw new Error(`Ключ ${path} должен содержать непустую строку`);
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
/** Принимает положительное безопасное целое число или отсутствие значения.
|
|
22
|
+
* @example getPositiveInteger(2, 'size') → 2; getPositiveInteger(0, 'size') → ошибка.
|
|
23
|
+
*/
|
|
24
|
+
export const getPositiveInteger = (value, path) => {
|
|
25
|
+
if (value == null) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 1) {
|
|
29
|
+
throw new Error(`Ключ ${path} должен быть положительным целым числом`);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
};
|
|
33
|
+
/** Проверяет необязательный логический флаг, не преобразуя строки в boolean.
|
|
34
|
+
* @example getBoolean(false, 'flag') → false; getBoolean('false', 'flag') → ошибка.
|
|
35
|
+
*/
|
|
36
|
+
export function getBoolean(value, path) {
|
|
37
|
+
if (value === undefined)
|
|
38
|
+
return undefined;
|
|
39
|
+
if (typeof value !== 'boolean')
|
|
40
|
+
throw new Error(`${path} must be boolean`);
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
/** Проверяет адрес и порт и подставляет значения по умолчанию.
|
|
44
|
+
* @example normalizeAddress({ port: 0 }) → { host: '127.0.0.1', port: 0 }.
|
|
45
|
+
*/
|
|
46
|
+
export function normalizeAddress(options) {
|
|
47
|
+
const host = getString(options.host, 'config.server.host') ?? DEFAULT_HOST;
|
|
48
|
+
const port = options.port ?? DEFAULT_PORT;
|
|
49
|
+
if (!isPortNumber(port))
|
|
50
|
+
throw new Error('Ключ config.server.port должен быть целым числом от 0 до 65535');
|
|
51
|
+
return { host, port };
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=config-values.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-values.js","sourceRoot":"","sources":["../../../src/core/config-values.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAOpD,MAAM,UAAU,SAAS,CAAC,KAAc,EAAE,IAAY,EAAE,QAAQ,GAAG,KAAK;IACtE,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,4BAA4B,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAOD,MAAM,UAAU,SAAS,CAAC,KAAc,EAAE,IAAY,EAAE,QAAQ,GAAG,KAAK;IACtE,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,mCAAmC,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAc,EAAE,IAAY,EAAsB,EAAE;IACrF,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,yCAAyC,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc,EAAE,IAAY;IACrD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,kBAAkB,CAAC,CAAC;IAC3E,OAAO,KAAK,CAAC;AACf,CAAC;AACD;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA2C;IAC1E,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,oBAAoB,CAAC,IAAI,YAAY,CAAC;IAC3E,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,YAAY,CAAC;IAC1C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IAC3G,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -3,4 +3,4 @@ export declare const DEFAULT_MAX_FILE_SIZE: number;
|
|
|
3
3
|
export declare const DEFAULT_MAX_PAGE_SIZE = 100;
|
|
4
4
|
export declare const DEFAULT_PAGE_SIZE = 10;
|
|
5
5
|
export declare const DEFAULT_PORT = 4001;
|
|
6
|
-
export declare const VERSION = "1.0.0-alpha.
|
|
6
|
+
export declare const VERSION = "1.0.0-alpha.8";
|
|
@@ -3,5 +3,5 @@ export const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024;
|
|
|
3
3
|
export const DEFAULT_MAX_PAGE_SIZE = 100;
|
|
4
4
|
export const DEFAULT_PAGE_SIZE = 10;
|
|
5
5
|
export const DEFAULT_PORT = 4001;
|
|
6
|
-
export const VERSION = '1.0.0-alpha.
|
|
6
|
+
export const VERSION = '1.0.0-alpha.8';
|
|
7
7
|
//# sourceMappingURL=constants.js.map
|