@volcanicminds/typeorm 2.0.1 → 2.1.1

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.
Files changed (110) hide show
  1. package/README.md +1 -0
  2. package/dist/index.d.ts +9 -8
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +67 -147
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/entities/change.d.ts +1 -0
  7. package/dist/lib/entities/change.d.ts.map +1 -0
  8. package/dist/lib/entities/change.js +2 -6
  9. package/dist/lib/entities/change.js.map +1 -1
  10. package/dist/lib/entities/token.d.ts +1 -0
  11. package/dist/lib/entities/token.d.ts.map +1 -0
  12. package/dist/lib/entities/token.js +2 -6
  13. package/dist/lib/entities/token.js.map +1 -1
  14. package/dist/lib/entities/user.d.ts +1 -0
  15. package/dist/lib/entities/user.d.ts.map +1 -0
  16. package/dist/lib/entities/user.js +2 -6
  17. package/dist/lib/entities/user.js.map +1 -1
  18. package/dist/lib/loader/dataBaseManager.d.ts +1 -0
  19. package/dist/lib/loader/dataBaseManager.d.ts.map +1 -0
  20. package/dist/lib/loader/dataBaseManager.js +29 -83
  21. package/dist/lib/loader/dataBaseManager.js.map +1 -1
  22. package/dist/lib/loader/entities.d.ts +1 -0
  23. package/dist/lib/loader/entities.d.ts.map +1 -0
  24. package/dist/lib/loader/entities.js +10 -8
  25. package/dist/lib/loader/entities.js.map +1 -1
  26. package/dist/lib/loader/tokenManager.d.ts +1 -0
  27. package/dist/lib/loader/tokenManager.d.ts.map +1 -0
  28. package/dist/lib/loader/tokenManager.js +101 -138
  29. package/dist/lib/loader/tokenManager.js.map +1 -1
  30. package/dist/lib/loader/userManager.d.ts +1 -0
  31. package/dist/lib/loader/userManager.d.ts.map +1 -0
  32. package/dist/lib/loader/userManager.js +234 -321
  33. package/dist/lib/loader/userManager.js.map +1 -1
  34. package/dist/lib/query/builder.d.ts +1 -0
  35. package/dist/lib/query/builder.d.ts.map +1 -0
  36. package/dist/lib/query/builder.js +4 -8
  37. package/dist/lib/query/builder.js.map +1 -1
  38. package/dist/lib/query/parser.d.ts +1 -0
  39. package/dist/lib/query/parser.d.ts.map +1 -0
  40. package/dist/lib/query/parser.js +2 -7
  41. package/dist/lib/query/parser.js.map +1 -1
  42. package/dist/lib/query.d.ts +1 -0
  43. package/dist/lib/query.d.ts.map +1 -0
  44. package/dist/lib/query.js +78 -110
  45. package/dist/lib/query.js.map +1 -1
  46. package/dist/lib/util/error.d.ts +5 -0
  47. package/dist/lib/util/error.d.ts.map +1 -0
  48. package/dist/lib/util/error.js +8 -0
  49. package/dist/lib/util/error.js.map +1 -0
  50. package/dist/lib/util/logger.d.ts +1 -0
  51. package/dist/lib/util/logger.d.ts.map +1 -0
  52. package/dist/lib/util/logger.js +12 -26
  53. package/dist/lib/util/logger.js.map +1 -1
  54. package/dist/lib/util/yn.d.ts +1 -0
  55. package/dist/lib/util/yn.d.ts.map +1 -0
  56. package/dist/lib/util/yn.js +1 -3
  57. package/dist/lib/util/yn.js.map +1 -1
  58. package/lib/entities/change.ts +11 -0
  59. package/lib/entities/token.ts +17 -0
  60. package/lib/entities/user.ts +24 -0
  61. package/lib/loader/dataBaseManager.ts +37 -0
  62. package/lib/loader/entities.ts +35 -0
  63. package/lib/loader/tokenManager.ts +128 -0
  64. package/lib/loader/userManager.ts +304 -0
  65. package/lib/query/builder.ts +38 -0
  66. package/lib/query/parser.ts +29 -0
  67. package/lib/query.ts +244 -0
  68. package/lib/util/error.ts +7 -0
  69. package/lib/util/logger.ts +23 -0
  70. package/lib/util/yn.ts +19 -0
  71. package/package.json +18 -26
  72. package/esm/index.d.ts +0 -12
  73. package/esm/index.js +0 -140
  74. package/esm/index.js.map +0 -1
  75. package/esm/lib/entities/change.d.ts +0 -10
  76. package/esm/lib/entities/change.js +0 -8
  77. package/esm/lib/entities/change.js.map +0 -1
  78. package/esm/lib/entities/token.d.ts +0 -15
  79. package/esm/lib/entities/token.js +0 -8
  80. package/esm/lib/entities/token.js.map +0 -1
  81. package/esm/lib/entities/user.d.ts +0 -22
  82. package/esm/lib/entities/user.js +0 -8
  83. package/esm/lib/entities/user.js.map +0 -1
  84. package/esm/lib/loader/dataBaseManager.d.ts +0 -4
  85. package/esm/lib/loader/dataBaseManager.js +0 -76
  86. package/esm/lib/loader/dataBaseManager.js.map +0 -1
  87. package/esm/lib/loader/entities.d.ts +0 -5
  88. package/esm/lib/loader/entities.js +0 -28
  89. package/esm/lib/loader/entities.js.map +0 -1
  90. package/esm/lib/loader/tokenManager.d.ts +0 -21
  91. package/esm/lib/loader/tokenManager.js +0 -128
  92. package/esm/lib/loader/tokenManager.js.map +0 -1
  93. package/esm/lib/loader/userManager.d.ts +0 -32
  94. package/esm/lib/loader/userManager.js +0 -341
  95. package/esm/lib/loader/userManager.js.map +0 -1
  96. package/esm/lib/query/builder.d.ts +0 -1
  97. package/esm/lib/query/builder.js +0 -37
  98. package/esm/lib/query/builder.js.map +0 -1
  99. package/esm/lib/query/parser.d.ts +0 -1
  100. package/esm/lib/query/parser.js +0 -32
  101. package/esm/lib/query/parser.js.map +0 -1
  102. package/esm/lib/query.d.ts +0 -33
  103. package/esm/lib/query.js +0 -210
  104. package/esm/lib/query.js.map +0 -1
  105. package/esm/lib/util/logger.d.ts +0 -6
  106. package/esm/lib/util/logger.js +0 -33
  107. package/esm/lib/util/logger.js.map +0 -1
  108. package/esm/lib/util/yn.d.ts +0 -1
  109. package/esm/lib/util/yn.js +0 -17
  110. package/esm/lib/util/yn.js.map +0 -1
@@ -0,0 +1,17 @@
1
+ import { BaseEntity } from 'typeorm'
2
+
3
+ export abstract class Token extends BaseEntity {
4
+ // abstract id: any
5
+ abstract externalId: string
6
+ abstract name: string
7
+ abstract description: string
8
+ abstract blocked: boolean
9
+ abstract blockedReason: string
10
+ abstract blockedAt: Date
11
+ abstract roles: string[]
12
+ abstract createdAt: Date
13
+ abstract updatedAt: Date
14
+ abstract deletedAt: Date
15
+ abstract setId(id: any)
16
+ abstract getId(): any
17
+ }
@@ -0,0 +1,24 @@
1
+ import { BaseEntity } from 'typeorm'
2
+
3
+ export abstract class User extends BaseEntity {
4
+ // abstract id: any
5
+ abstract externalId: string
6
+ abstract username: string
7
+ abstract email: string
8
+ abstract password: string
9
+ abstract confirmed: boolean
10
+ abstract confirmedAt: Date
11
+ abstract passwordChangedAt: Date
12
+ abstract blocked: boolean
13
+ abstract blockedReason: string
14
+ abstract blockedAt: Date
15
+ abstract resetPasswordToken: string
16
+ abstract confirmationToken: string
17
+ abstract roles: string[]
18
+ abstract version: number
19
+ abstract createdAt: Date
20
+ abstract updatedAt: Date
21
+ abstract deletedAt: Date
22
+ abstract setId(id: any)
23
+ abstract getId(): any
24
+ }
@@ -0,0 +1,37 @@
1
+ import * as log from '../util/logger.js'
2
+
3
+ export function isImplemented() {
4
+ return true
5
+ }
6
+
7
+ export async function synchronizeSchemas() {
8
+ try {
9
+ await global.connection.synchronize()
10
+ return true
11
+ } catch (error) {
12
+ throw error
13
+ }
14
+ }
15
+
16
+ export async function retrieveBy(entityName, entityId) {
17
+ try {
18
+ return await global.entity[entityName].findOneById(entityId)
19
+ } catch (error) {
20
+ if (!(entityName in global.entity)) {
21
+ log.error(`${entityName} not found in global.entity`)
22
+ }
23
+ throw error
24
+ }
25
+ }
26
+
27
+ export async function addChange(entityName, entityId, status, userId, contents, changeEntity = 'Change') {
28
+ try {
29
+ const newChange = await global.entity[changeEntity].create({ entityName, entityId, status, userId, contents })
30
+ return global.entity[changeEntity].save(newChange)
31
+ } catch (error) {
32
+ if (!(changeEntity in global.entity)) {
33
+ log.error(`${changeEntity} not found in global.entity`)
34
+ }
35
+ throw error
36
+ }
37
+ }
@@ -0,0 +1,35 @@
1
+ import * as path from 'path'
2
+ import { globSync } from 'glob'
3
+ import pluralize from 'pluralize'
4
+ import { createRequire } from 'module'
5
+ import { fileURLToPath } from 'url'
6
+
7
+ const require = createRequire(import.meta.url)
8
+ const __filename = fileURLToPath(import.meta.url)
9
+ const __dirname = path.dirname(__filename)
10
+
11
+ export function load() {
12
+ const classes: any = {}
13
+ const repositories: any = {}
14
+ const entities: any[] = []
15
+
16
+ const patterns = [
17
+ path.join(__dirname, '..', 'entities', '*.e.{ts,js}'),
18
+ path.join(process.cwd(), 'src', 'entities', '*.e.{ts,js}')
19
+ ]
20
+
21
+ patterns.forEach((pattern) => {
22
+ globSync(pattern, { nodir: true, windowsPathsNoEscape: true }).forEach((f: string) => {
23
+ const entityClass = require(f)
24
+ const entityNames = Object.keys(entityClass)
25
+
26
+ entityNames.map((name) => {
27
+ classes[name] = entityClass[name]
28
+ repositories[pluralize(name.toLowerCase())] = entityClass[name]
29
+ entities.push(entityClass[name])
30
+ })
31
+ })
32
+ })
33
+
34
+ return { classes, repositories, entities }
35
+ }
@@ -0,0 +1,128 @@
1
+ import * as Crypto from 'crypto'
2
+ import { ServiceError } from '../util/error.js'
3
+ import { executeCountQuery, executeFindQuery } from '../query.js'
4
+
5
+ export function isImplemented() {
6
+ return true
7
+ }
8
+
9
+ export async function isValidToken(data: typeof global.entity.Token) {
10
+ return !!data && (!!data._id || !!data.id) && !!data.externalId && !!data.name
11
+ }
12
+
13
+ export async function createToken(data: typeof global.entity.Token) {
14
+ const { name, description } = data
15
+
16
+ if (!name) {
17
+ throw new ServiceError('Invalid parameters', 400)
18
+ }
19
+
20
+ try {
21
+ let externalId, token
22
+ do {
23
+ externalId = Crypto.randomUUID({ disableEntropyCache: true })
24
+
25
+ token = await global.repository.tokens.findOneBy({ externalId: externalId })
26
+ } while (token != null)
27
+
28
+ token = await global.entity.Token.create({
29
+ ...data,
30
+ name: name,
31
+ description: description,
32
+ blocked: false,
33
+ blockedReason: null,
34
+ externalId: externalId
35
+ } as typeof global.entity.Token)
36
+
37
+ return await global.entity.Token.save(token)
38
+ } catch (error) {
39
+ throw error
40
+ }
41
+ }
42
+
43
+ export async function resetExternalId(id: string) {
44
+ if (!id) {
45
+ throw new ServiceError('Invalid parameters', 400)
46
+ }
47
+
48
+ try {
49
+ let externalId, token
50
+ do {
51
+ externalId = Crypto.randomUUID({ disableEntropyCache: true })
52
+ token = await global.repository.tokens.findOneBy({ externalId: externalId })
53
+ } while (token != null)
54
+
55
+ // TODO: use externalId instead id
56
+ return await updateTokenById(id, { externalId: externalId })
57
+ } catch (error) {
58
+ if (error?.code == 23505) {
59
+ throw new Error('External ID not changed')
60
+ }
61
+ throw error
62
+ }
63
+ }
64
+
65
+ export async function updateTokenById(id: string, token: typeof global.entity.Token) {
66
+ if (!id || !token) {
67
+ throw new ServiceError('Invalid parameters', 400)
68
+ }
69
+ try {
70
+ const tokenEx = await global.repository.tokens.findOneById(id)
71
+ if (!tokenEx) {
72
+ throw new ServiceError('Token not found', 404)
73
+ }
74
+ const merged = global.repository.tokens.merge(tokenEx, token)
75
+ return await global.entity.Token.save(merged)
76
+ } catch (error) {
77
+ throw error
78
+ }
79
+ }
80
+
81
+ export async function retrieveTokenById(id: string) {
82
+ if (!id) {
83
+ throw new ServiceError('Invalid parameters', 400)
84
+ }
85
+ try {
86
+ return await global.repository.tokens.findOneById(id)
87
+ } catch (error) {
88
+ throw error
89
+ }
90
+ }
91
+
92
+ export async function retrieveTokenByExternalId(externalId: string) {
93
+ if (!externalId) {
94
+ throw new ServiceError('Invalid parameters', 400)
95
+ }
96
+ try {
97
+ return await global.repository.tokens.findOneBy({ externalId: externalId })
98
+ } catch (error) {
99
+ throw error
100
+ }
101
+ }
102
+
103
+ export async function blockTokenById(id: string, reason: string) {
104
+ return updateTokenById(id, { blocked: true, blockedAt: new Date(), blockedReason: reason })
105
+ }
106
+
107
+ export async function unblockTokenById(id: string) {
108
+ return updateTokenById(id, { blocked: false, blockedAt: new Date(), blockedReason: null })
109
+ }
110
+
111
+ export async function countQuery(data: any) {
112
+ return await executeCountQuery(global.repository.tokens, data, {})
113
+ }
114
+
115
+ export async function findQuery(data: any) {
116
+ return await executeFindQuery(global.repository.tokens, {}, data)
117
+ }
118
+
119
+ export async function removeTokenById(id: string) {
120
+ if (!id) {
121
+ throw new ServiceError('Invalid parameters', 400)
122
+ }
123
+ try {
124
+ return await global.repository.tokens.delete(id)
125
+ } catch (error) {
126
+ throw error
127
+ }
128
+ }
@@ -0,0 +1,304 @@
1
+ import * as bcrypt from 'bcrypt'
2
+ import * as Crypto from 'crypto'
3
+ import { ServiceError } from '../util/error.js'
4
+ import { executeCountQuery, executeFindQuery } from '../query.js'
5
+
6
+ export function isImplemented() {
7
+ return true
8
+ }
9
+
10
+ export async function isValidUser(data: typeof global.entity.User) {
11
+ return !!data && (!!data._id || !!data.id) && !!data.externalId && !!data.email && !!data.password
12
+ }
13
+
14
+ export async function createUser(data: typeof global.entity.User) {
15
+ const { username, email, password } = data
16
+
17
+ if (!email || !password) {
18
+ throw new ServiceError('Invalid parameters', 400)
19
+ }
20
+
21
+ const salt = await bcrypt.genSalt(12)
22
+ const hashedPassword = await bcrypt.hash(password, salt)
23
+
24
+ try {
25
+ let externalId, user
26
+ do {
27
+ externalId = Crypto.randomUUID({ disableEntropyCache: true })
28
+
29
+ user = await global.repository.users.findOneBy({ externalId: externalId })
30
+ } while (user != null)
31
+
32
+ user = await global.entity.User.create({
33
+ ...data,
34
+ passwordChangedAt: new Date(),
35
+ confirmed: false,
36
+ confirmationToken: Crypto.randomBytes(64).toString('hex'),
37
+ blocked: false,
38
+ blockedReason: null,
39
+ externalId: externalId,
40
+ email: email,
41
+ username: username || email,
42
+ password: hashedPassword
43
+ } as typeof global.entity.User)
44
+
45
+ return await global.entity.User.save(user)
46
+ } catch (error) {
47
+ if (error?.code == 23505) {
48
+ throw new ServiceError('Email or username already registered', 409)
49
+ }
50
+ throw error
51
+ }
52
+ }
53
+
54
+ export async function deleteUser(id: string) {
55
+ if (!id) {
56
+ throw new ServiceError('Invalid parameters', 400)
57
+ }
58
+
59
+ try {
60
+ const userEx = await retrieveUserById(id)
61
+ if (!userEx) {
62
+ throw new ServiceError('User not found', 404)
63
+ }
64
+
65
+ return global.entity.User.delete(id)
66
+ } catch (error) {
67
+ throw error
68
+ }
69
+ }
70
+
71
+ export async function resetExternalId(id: string) {
72
+ if (!id) {
73
+ throw new ServiceError('Invalid parameters', 400)
74
+ }
75
+
76
+ try {
77
+ let externalId, user
78
+ do {
79
+ externalId = Crypto.randomUUID({ disableEntropyCache: true })
80
+ user = await global.repository.users.findOneBy({ externalId: externalId })
81
+ } while (user != null)
82
+
83
+ // TODO: use externalId instead id
84
+ return await updateUserById(id, { externalId: externalId })
85
+ } catch (error) {
86
+ if (error?.code == 23505) {
87
+ throw new ServiceError('External ID not changed', 409)
88
+ }
89
+ throw error
90
+ }
91
+ }
92
+
93
+ export async function updateUserById(id: string, user: typeof global.entity.User) {
94
+ if (!id || !user) {
95
+ throw new ServiceError('Invalid parameters', 400)
96
+ }
97
+ try {
98
+ const userEx = await retrieveUserById(id)
99
+ if (!userEx) {
100
+ throw new ServiceError('User not found', 404)
101
+ }
102
+ const merged = global.repository.users.merge(userEx, user)
103
+ return await global.entity.User.save(merged)
104
+ } catch (error) {
105
+ throw error
106
+ }
107
+ }
108
+
109
+ export async function retrieveUserById(id: string) {
110
+ if (!id) {
111
+ throw new ServiceError('Invalid parameters', 400)
112
+ }
113
+ try {
114
+ return await global.repository.users.findOneById(id)
115
+ } catch (error) {
116
+ throw error
117
+ }
118
+ }
119
+
120
+ export async function retrieveUserByEmail(email: string) {
121
+ if (!email) {
122
+ throw new ServiceError('Invalid parameters', 400)
123
+ }
124
+ try {
125
+ return await global.repository.users.findOneBy({ email: email })
126
+ } catch (error) {
127
+ throw error
128
+ }
129
+ }
130
+
131
+ export async function retrieveUserByUsername(username: string) {
132
+ if (!username) {
133
+ throw new ServiceError('Invalid parameters', 400)
134
+ }
135
+ try {
136
+ return await global.repository.users.findOneBy({ username })
137
+ } catch (error) {
138
+ throw error
139
+ }
140
+ }
141
+
142
+ export async function retrieveUserByConfirmationToken(code: string) {
143
+ if (!code) {
144
+ throw new ServiceError('Invalid parameters', 400)
145
+ }
146
+ try {
147
+ return await global.repository.users.findOneBy({ confirmationToken: code })
148
+ } catch (error) {
149
+ throw error
150
+ }
151
+ }
152
+
153
+ export async function retrieveUserByResetPasswordToken(code: string) {
154
+ if (!code) {
155
+ throw new ServiceError('Invalid parameters', 400)
156
+ }
157
+ try {
158
+ return await global.repository.users.findOneBy({ resetPasswordToken: code })
159
+ } catch (error) {
160
+ throw error
161
+ }
162
+ }
163
+
164
+ export async function retrieveUserByExternalId(externalId: string) {
165
+ if (!externalId) {
166
+ throw new ServiceError('Invalid parameters', 400)
167
+ }
168
+ try {
169
+ return await global.repository.users.findOne({
170
+ where: { externalId: externalId },
171
+ cache: global.cacheTimeout
172
+ })
173
+ } catch (error) {
174
+ throw error
175
+ }
176
+ }
177
+
178
+ export async function retrieveUserByPassword(email: string, password: string) {
179
+ if (!email || !password) {
180
+ throw new ServiceError('Invalid parameters', 400)
181
+ }
182
+ try {
183
+ const user = await global.repository.users.findOneBy({ email: email })
184
+ if (!user) {
185
+ throw new Error('Wrong credentials')
186
+ }
187
+ const match = await bcrypt.compare(password, user.password)
188
+ return match ? user : null
189
+ } catch (error) {
190
+ throw error
191
+ }
192
+ }
193
+
194
+ export async function changePassword(email: string, password: string, oldPassword: string) {
195
+ if (!email || !password || !oldPassword) {
196
+ throw new ServiceError('Invalid parameters', 400)
197
+ }
198
+ try {
199
+ const user = await global.repository.users.findOneBy({ email: email })
200
+ const match = await bcrypt.compare(oldPassword, user.password)
201
+ if (match) {
202
+ const salt = await bcrypt.genSalt(12)
203
+ const hashedPassword = await bcrypt.hash(password, salt)
204
+ return await global.entity.User.save({ ...user, passwordChangedAt: new Date(), password: hashedPassword })
205
+ }
206
+ throw new ServiceError('Password not changed', 400)
207
+ } catch (error) {
208
+ throw error
209
+ }
210
+ }
211
+
212
+ export async function forgotPassword(email: string) {
213
+ if (!email) {
214
+ throw new ServiceError('Invalid parameters', 400)
215
+ }
216
+ try {
217
+ const user = await global.repository.users.findOneBy({ email: email })
218
+
219
+ if (user) {
220
+ return await global.entity.User.save({
221
+ ...user,
222
+ resetPasswordToken: Crypto.randomBytes(64).toString('hex')
223
+ })
224
+ }
225
+ throw new ServiceError('Password not changed', 400)
226
+ } catch (error) {
227
+ throw error
228
+ }
229
+ }
230
+
231
+ export async function resetPassword(user: typeof global.entity.User, password: string) {
232
+ if (!user || !password) {
233
+ throw new ServiceError('Invalid parameters', 400)
234
+ }
235
+ try {
236
+ const salt = await bcrypt.genSalt(12)
237
+ const hashedPassword = await bcrypt.hash(password, salt)
238
+ return await global.entity.User.save({
239
+ ...user,
240
+ passwordChangedAt: new Date(),
241
+ confirmed: true,
242
+ confirmedAt: new Date(),
243
+ resetPasswordToken: null,
244
+ password: hashedPassword
245
+ })
246
+ } catch (error) {
247
+ throw error
248
+ }
249
+ }
250
+
251
+ export async function userConfirmation(user: typeof global.entity.User) {
252
+ if (!user) {
253
+ throw new ServiceError('Invalid parameters', 400)
254
+ }
255
+ try {
256
+ return await global.entity.User.save({ ...user, confirmed: true, confirmedAt: new Date(), confirmationToken: null })
257
+ } catch (error) {
258
+ throw error
259
+ }
260
+ }
261
+
262
+ export async function blockUserById(id: string, reason: string) {
263
+ return updateUserById(id, { blocked: true, blockedAt: new Date(), blockedReason: reason })
264
+ }
265
+
266
+ export async function unblockUserById(id: string) {
267
+ return updateUserById(id, { blocked: false, blockedAt: new Date(), blockedReason: null })
268
+ }
269
+
270
+ export function isPasswordToBeChanged(user: typeof global.entity.User) {
271
+ if (process.env.PASSWORD_EXPIRATION_DAYS != null) {
272
+ let passwordExpirationDays = -1
273
+ try {
274
+ passwordExpirationDays = Number(process.env.PASSWORD_EXPIRATION_DAYS)
275
+ if (passwordExpirationDays <= 0) {
276
+ throw new Error('PASSWORD_EXPIRATION_DAYS_ENV_INVALID')
277
+ }
278
+ } catch (e) {
279
+ throw new Error(e)
280
+ }
281
+ const { passwordChangedAt } = user
282
+ const date1 = new Date(passwordChangedAt)
283
+ const date2 = new Date()
284
+ const differenceInTime = date2.getTime() - date1.getTime()
285
+ const differenceInDays = differenceInTime / (1000 * 3600 * 24)
286
+
287
+ return differenceInDays >= passwordExpirationDays
288
+ }
289
+
290
+ return false
291
+ }
292
+
293
+ export async function countQuery(data: any) {
294
+ return await executeCountQuery(global.repository.users, data)
295
+ }
296
+
297
+ export async function findQuery(data: any) {
298
+ return await executeFindQuery(global.repository.users, {}, data)
299
+ }
300
+
301
+ export async function disableUserById(id: string) {
302
+ await updateUserById(id, { blocked: true, blockedAt: new Date(), blockedReason: 'User disabled to unregister' })
303
+ return resetExternalId(id)
304
+ }
@@ -0,0 +1,38 @@
1
+ const combineSqlAnd = (left, right) => {
2
+ if (Array.isArray(left) || Array.isArray(right)) {
3
+ throw new Error('Combining OR conditions with AND is not supported in this simplified SQL builder.')
4
+ }
5
+ return { ...left, ...right }
6
+ }
7
+
8
+ export const buildWhereFromAst = (ast: any, aliasMap: Map<string, any>, isMongo: boolean) => {
9
+ if (!ast) {
10
+ return {}
11
+ }
12
+
13
+ if (ast.type === 'operand') {
14
+ if (!aliasMap.has(ast.value)) {
15
+ throw new Error(`Alias "${ast.value}" used in _logic not found in query parameters.`)
16
+ }
17
+ return aliasMap.get(ast.value)
18
+ }
19
+
20
+ const left = buildWhereFromAst(ast.left, aliasMap, isMongo)
21
+ const right = buildWhereFromAst(ast.right, aliasMap, isMongo)
22
+
23
+ if (ast.type === 'AND') {
24
+ if (isMongo) {
25
+ return { $and: [left, right].flat() }
26
+ }
27
+ return combineSqlAnd(left, right)
28
+ }
29
+
30
+ if (ast.type === 'OR') {
31
+ if (isMongo) {
32
+ return { $or: [left, right].flat() }
33
+ }
34
+ return [left, right].flat()
35
+ }
36
+
37
+ return {}
38
+ }
@@ -0,0 +1,29 @@
1
+ export const parseLogicExpression = (logic: string) => {
2
+ const tokens = logic.match(/\(|\)|[A-Za-z0-9_:]+|\s*(AND|OR)\s*/g)?.filter((t) => t.trim()) || []
3
+ let pos = 0
4
+
5
+ const parseExpression = () => {
6
+ let left = parseTerm()
7
+ while (pos < tokens.length && (tokens[pos].trim() === 'OR' || tokens[pos].trim() === 'AND')) {
8
+ const operator = tokens[pos++].trim()
9
+ const right = parseTerm()
10
+ left = { type: operator, left, right }
11
+ }
12
+ return left
13
+ }
14
+
15
+ const parseTerm = () => {
16
+ if (tokens[pos] === '(') {
17
+ pos++
18
+ const node = parseExpression()
19
+ if (tokens[pos] !== ')') {
20
+ throw new Error('Mismatched parentheses in _logic expression')
21
+ }
22
+ pos++
23
+ return node
24
+ }
25
+ return { type: 'operand', value: tokens[pos++] }
26
+ }
27
+
28
+ return parseExpression()
29
+ }