@volcanicminds/backend 2.3.1 → 3.0.0
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 +240 -28
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -36
- package/dist/index.js.map +1 -1
- package/dist/lib/api/auth/controller/auth.d.ts.map +1 -1
- package/dist/lib/api/auth/controller/auth.js +14 -7
- package/dist/lib/api/auth/controller/auth.js.map +1 -1
- package/dist/lib/api/health/controller/health.d.ts +1 -1
- package/dist/lib/api/health/controller/health.d.ts.map +1 -1
- package/dist/lib/api/health/controller/health.js +1 -1
- package/dist/lib/api/health/controller/health.js.map +1 -1
- package/dist/lib/api/health/routes.d.ts +1 -0
- package/dist/lib/api/health/routes.d.ts.map +1 -1
- package/dist/lib/api/health/routes.js +1 -0
- package/dist/lib/api/health/routes.js.map +1 -1
- package/dist/lib/api/tenants/controller/tenants.d.ts +17 -0
- package/dist/lib/api/tenants/controller/tenants.d.ts.map +1 -0
- package/dist/lib/api/tenants/controller/tenants.js +150 -0
- package/dist/lib/api/tenants/controller/tenants.js.map +1 -0
- package/dist/lib/api/tenants/routes.d.ts +167 -0
- package/dist/lib/api/tenants/routes.d.ts.map +1 -0
- package/dist/lib/api/tenants/routes.js +143 -0
- package/dist/lib/api/tenants/routes.js.map +1 -0
- package/dist/lib/config/plugins.js +1 -1
- package/dist/lib/config/plugins.js.map +1 -1
- package/dist/lib/database/typeorm/entities/change.d.ts +11 -0
- package/dist/lib/database/typeorm/entities/change.d.ts.map +1 -0
- package/dist/lib/database/typeorm/entities/change.js +4 -0
- package/dist/lib/database/typeorm/entities/change.js.map +1 -0
- package/dist/lib/database/typeorm/entities/tenant.d.ts +13 -0
- package/dist/lib/database/typeorm/entities/tenant.d.ts.map +1 -0
- package/dist/lib/database/typeorm/entities/tenant.js +4 -0
- package/dist/lib/database/typeorm/entities/tenant.js.map +1 -0
- package/dist/lib/database/typeorm/entities/token.d.ts +16 -0
- package/dist/lib/database/typeorm/entities/token.d.ts.map +1 -0
- package/dist/lib/database/typeorm/entities/token.js +4 -0
- package/dist/lib/database/typeorm/entities/token.js.map +1 -0
- package/dist/lib/database/typeorm/entities/user.d.ts +28 -0
- package/dist/lib/database/typeorm/entities/user.d.ts.map +1 -0
- package/dist/lib/database/typeorm/entities/user.js +4 -0
- package/dist/lib/database/typeorm/entities/user.js.map +1 -0
- package/dist/lib/database/typeorm/loader/dataBaseManager.d.ts +6 -0
- package/dist/lib/database/typeorm/loader/dataBaseManager.d.ts.map +1 -0
- package/dist/lib/database/typeorm/loader/dataBaseManager.js +73 -0
- package/dist/lib/database/typeorm/loader/dataBaseManager.js.map +1 -0
- package/dist/lib/database/typeorm/loader/entities.d.ts +6 -0
- package/dist/lib/database/typeorm/loader/entities.d.ts.map +1 -0
- package/dist/lib/database/typeorm/loader/entities.js +37 -0
- package/dist/lib/database/typeorm/loader/entities.js.map +1 -0
- package/dist/lib/database/typeorm/loader/tenantManager.d.ts +17 -0
- package/dist/lib/database/typeorm/loader/tenantManager.d.ts.map +1 -0
- package/dist/lib/database/typeorm/loader/tenantManager.js +193 -0
- package/dist/lib/database/typeorm/loader/tenantManager.js.map +1 -0
- package/dist/lib/database/typeorm/loader/tokenManager.d.ts +23 -0
- package/dist/lib/database/typeorm/loader/tokenManager.d.ts.map +1 -0
- package/dist/lib/database/typeorm/loader/tokenManager.js +131 -0
- package/dist/lib/database/typeorm/loader/tokenManager.js.map +1 -0
- package/dist/lib/database/typeorm/loader/userManager.d.ts +39 -0
- package/dist/lib/database/typeorm/loader/userManager.d.ts.map +1 -0
- package/dist/lib/database/typeorm/loader/userManager.js +358 -0
- package/dist/lib/database/typeorm/loader/userManager.js.map +1 -0
- package/dist/lib/database/typeorm/query/builder.d.ts +2 -0
- package/dist/lib/database/typeorm/query/builder.d.ts.map +1 -0
- package/dist/lib/database/typeorm/query/builder.js +33 -0
- package/dist/lib/database/typeorm/query/builder.js.map +1 -0
- package/dist/lib/database/typeorm/query/parser.d.ts +2 -0
- package/dist/lib/database/typeorm/query/parser.d.ts.map +1 -0
- package/dist/lib/database/typeorm/query/parser.js +27 -0
- package/dist/lib/database/typeorm/query/parser.js.map +1 -0
- package/dist/lib/database/typeorm/query.d.ts +36 -0
- package/dist/lib/database/typeorm/query.d.ts.map +1 -0
- package/dist/lib/database/typeorm/query.js +259 -0
- package/dist/lib/database/typeorm/query.js.map +1 -0
- package/dist/lib/database/typeorm/util/crypto.d.ts +3 -0
- package/dist/lib/database/typeorm/util/crypto.d.ts.map +1 -0
- package/dist/lib/database/typeorm/util/crypto.js +46 -0
- package/dist/lib/database/typeorm/util/crypto.js.map +1 -0
- package/dist/lib/database/typeorm/util/error.d.ts +5 -0
- package/dist/lib/database/typeorm/util/error.d.ts.map +1 -0
- package/dist/lib/database/typeorm/util/error.js +8 -0
- package/dist/lib/database/typeorm/util/error.js.map +1 -0
- package/dist/lib/database/typeorm/util/logger.d.ts +7 -0
- package/dist/lib/database/typeorm/util/logger.d.ts.map +1 -0
- package/dist/lib/database/typeorm/util/logger.js +31 -0
- package/dist/lib/database/typeorm/util/logger.js.map +1 -0
- package/dist/lib/database/typeorm/util/yn.d.ts +2 -0
- package/dist/lib/database/typeorm/util/yn.d.ts.map +1 -0
- package/dist/lib/database/typeorm/util/yn.js +15 -0
- package/dist/lib/database/typeorm/util/yn.js.map +1 -0
- package/dist/lib/defaults/managers.d.ts.map +1 -1
- package/dist/lib/defaults/managers.js +186 -58
- package/dist/lib/defaults/managers.js.map +1 -1
- package/dist/lib/hooks/onRequest.d.ts.map +1 -1
- package/dist/lib/hooks/onRequest.js +11 -48
- package/dist/lib/hooks/onRequest.js.map +1 -1
- package/dist/lib/loader/router.d.ts.map +1 -1
- package/dist/lib/loader/router.js +92 -83
- package/dist/lib/loader/router.js.map +1 -1
- package/dist/lib/loader/tenant.d.ts.map +1 -1
- package/dist/lib/loader/tenant.js +25 -2
- package/dist/lib/loader/tenant.js.map +1 -1
- package/dist/lib/locales/en.json +12 -0
- package/dist/lib/locales/it.json +12 -0
- package/dist/lib/schemas/tenant.d.ts +88 -0
- package/dist/lib/schemas/tenant.d.ts.map +1 -0
- package/dist/lib/schemas/tenant.js +45 -0
- package/dist/lib/schemas/tenant.js.map +1 -0
- package/dist/lib/util/regexp.d.ts +2 -0
- package/dist/lib/util/regexp.d.ts.map +1 -1
- package/dist/lib/util/regexp.js +5 -3
- package/dist/lib/util/regexp.js.map +1 -1
- package/dist/lib/util/secret.d.ts +11 -0
- package/dist/lib/util/secret.d.ts.map +1 -0
- package/dist/lib/util/secret.js +70 -0
- package/dist/lib/util/secret.js.map +1 -0
- package/dist/server.js +4 -1
- package/dist/server.js.map +1 -1
- package/dist/typeorm.d.ts +15 -0
- package/dist/typeorm.d.ts.map +1 -0
- package/dist/typeorm.js +86 -0
- package/dist/typeorm.js.map +1 -0
- package/dist/types/database/typeorm/global.d.ts +56 -0
- package/dist/types/database/typeorm/global.d.ts.map +1 -0
- package/dist/types/database/typeorm/global.js +2 -0
- package/dist/types/database/typeorm/global.js.map +1 -0
- package/dist/types/global.d.ts +318 -0
- package/dist/types/orm.d.ts +22 -0
- package/lib/api/auth/controller/auth.ts +28 -12
- package/lib/api/health/controller/health.ts +1 -1
- package/lib/api/health/routes.ts +1 -0
- package/lib/api/tenants/controller/tenants.ts +211 -0
- package/lib/api/tenants/routes.ts +145 -0
- package/lib/config/plugins.ts +1 -1
- package/lib/database/typeorm/entities/change.ts +11 -0
- package/lib/database/typeorm/entities/tenant.ts +20 -0
- package/lib/database/typeorm/entities/token.ts +18 -0
- package/lib/database/typeorm/entities/user.ts +33 -0
- package/lib/database/typeorm/loader/dataBaseManager.ts +89 -0
- package/lib/database/typeorm/loader/entities.ts +47 -0
- package/lib/database/typeorm/loader/tenantManager.ts +260 -0
- package/lib/database/typeorm/loader/tokenManager.ts +157 -0
- package/lib/database/typeorm/loader/userManager.ts +432 -0
- package/lib/database/typeorm/query/builder.ts +39 -0
- package/lib/database/typeorm/query/parser.ts +29 -0
- package/lib/database/typeorm/query.ts +326 -0
- package/lib/database/typeorm/util/crypto.ts +52 -0
- package/lib/database/typeorm/util/error.ts +7 -0
- package/lib/database/typeorm/util/logger.ts +35 -0
- package/lib/database/typeorm/util/yn.ts +20 -0
- package/lib/defaults/managers.ts +191 -64
- package/lib/hooks/onRequest.ts +12 -64
- package/lib/loader/router.ts +133 -110
- package/lib/loader/tenant.ts +37 -14
- package/lib/schemas/tenant.ts +49 -0
- package/lib/util/regexp.ts +31 -8
- package/lib/util/secret.ts +113 -0
- package/package.json +54 -13
- package/dist/lib/apollo/context.d.ts +0 -6
- package/dist/lib/apollo/context.d.ts.map +0 -1
- package/dist/lib/apollo/context.js +0 -5
- package/dist/lib/apollo/context.js.map +0 -1
- package/dist/lib/apollo/resolvers.d.ts +0 -8
- package/dist/lib/apollo/resolvers.d.ts.map +0 -1
- package/dist/lib/apollo/resolvers.js +0 -8
- package/dist/lib/apollo/resolvers.js.map +0 -1
- package/dist/lib/apollo/type-defs.d.ts +0 -3
- package/dist/lib/apollo/type-defs.d.ts.map +0 -1
- package/dist/lib/apollo/type-defs.js +0 -8
- package/dist/lib/apollo/type-defs.js.map +0 -1
- package/lib/apollo/context.ts +0 -11
- package/lib/apollo/resolvers.ts +0 -12
- package/lib/apollo/type-defs.ts +0 -9
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
/* eslint-disable prefer-const */
|
|
3
|
+
import {
|
|
4
|
+
Not,
|
|
5
|
+
Like,
|
|
6
|
+
ILike,
|
|
7
|
+
Raw,
|
|
8
|
+
Equal,
|
|
9
|
+
IsNull,
|
|
10
|
+
In,
|
|
11
|
+
Between,
|
|
12
|
+
MoreThan,
|
|
13
|
+
MoreThanOrEqual,
|
|
14
|
+
LessThan,
|
|
15
|
+
LessThanOrEqual,
|
|
16
|
+
QueryRunner
|
|
17
|
+
} from 'typeorm'
|
|
18
|
+
import yn from './util/yn.js'
|
|
19
|
+
import * as log from './util/logger.js'
|
|
20
|
+
import { parseLogicExpression } from './query/parser.js'
|
|
21
|
+
import { buildWhereFromAst } from './query/builder.js'
|
|
22
|
+
|
|
23
|
+
let sensitiveFields = ['password', 'mfaSecret', 'resetPasswordToken', 'confirmationToken']
|
|
24
|
+
|
|
25
|
+
export const configureSensitiveFields = (fields: string[]) => {
|
|
26
|
+
if (fields && Array.isArray(fields)) {
|
|
27
|
+
log.info(`Volcanic-TypeORM: Overrided sensitive fields: ${fields.join(', ')}`)
|
|
28
|
+
sensitiveFields = fields
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const evalOrder = (val: string = '') => (['desc', 'd', 'false', '1'].includes(val.toLowerCase()) ? 'desc' : 'asc')
|
|
33
|
+
|
|
34
|
+
const escapeRegExp = (str: string) => {
|
|
35
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const isValidIdentifier = (str: string) => /^[a-zA-Z0-9_.]+$/.test(str)
|
|
39
|
+
|
|
40
|
+
const hasProtoRisk = (str: string) => ['__proto__', 'constructor', 'prototype'].includes(str)
|
|
41
|
+
|
|
42
|
+
export const useOrder = (order: string[] = []) => {
|
|
43
|
+
const result = {}
|
|
44
|
+
order
|
|
45
|
+
.filter((o) => !!o)
|
|
46
|
+
.forEach((o: string) => {
|
|
47
|
+
const parts = o.split(':')
|
|
48
|
+
const fieldFullPath = parts[0].split('.')
|
|
49
|
+
|
|
50
|
+
// Controllo sicurezza identificatore
|
|
51
|
+
if (!isValidIdentifier(parts[0])) {
|
|
52
|
+
log.warn(`Volcanic-TypeORM: Invalid sort field skipped: ${parts[0]}`)
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const sortType = evalOrder(parts[1])
|
|
57
|
+
|
|
58
|
+
let target = result
|
|
59
|
+
while (fieldFullPath.length > 1) {
|
|
60
|
+
const fieldPath: string = fieldFullPath.shift() || ''
|
|
61
|
+
if (hasProtoRisk(fieldPath)) {
|
|
62
|
+
continue
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
target = target[fieldPath] = target[fieldPath] || {}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const fieldName = fieldFullPath[0]
|
|
69
|
+
if (hasProtoRisk(fieldName)) {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
target[fieldName] = sortType
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
return result
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const typecastValue = (value: any) => {
|
|
80
|
+
if (typeof value !== 'string') return value
|
|
81
|
+
const lowerValue = value.toLowerCase()
|
|
82
|
+
if (lowerValue === 'true') return true
|
|
83
|
+
if (lowerValue === 'false') return false
|
|
84
|
+
if (lowerValue === 'null') return null
|
|
85
|
+
return value
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export const useWhere = (where: any, repo?: any) => {
|
|
89
|
+
const aliasMap = new Map<string, any>()
|
|
90
|
+
const isTargetMongo = isMongo(repo)
|
|
91
|
+
const val = (v) => v || 'notFound'
|
|
92
|
+
|
|
93
|
+
const reservedOperators = {
|
|
94
|
+
':null': (v) => (typecastValue(v) === false ? Not(IsNull()) : IsNull()),
|
|
95
|
+
':notNull': (v) => (typecastValue(v) === true ? Not(IsNull()) : IsNull()),
|
|
96
|
+
':in': (v) => In(val(v).split(',').map(typecastValue)),
|
|
97
|
+
':nin': (v) => Not(In(val(v).split(',').map(typecastValue))),
|
|
98
|
+
':likei': (v) => (isTargetMongo ? new RegExp(escapeRegExp(val(v)), 'i') : ILike(`%${val(v)}%`)),
|
|
99
|
+
':containsi': (v) => (isTargetMongo ? new RegExp(escapeRegExp(val(v)), 'i') : ILike(`%${val(v)}%`)),
|
|
100
|
+
':ncontainsi': (v) => (isTargetMongo ? Not(new RegExp(escapeRegExp(val(v)), 'i')) : Not(ILike(`%${val(v)}%`))),
|
|
101
|
+
':startsi': (v) => (isTargetMongo ? new RegExp(`^${escapeRegExp(val(v))}`, 'i') : ILike(`${val(v)}%`)),
|
|
102
|
+
':endsi': (v) => (isTargetMongo ? new RegExp(`${escapeRegExp(val(v))}$`, 'i') : ILike(`%${val(v)}`)),
|
|
103
|
+
':eqi': (v) => (isTargetMongo ? new RegExp(`^${escapeRegExp(val(v))}$`, 'i') : ILike(v)),
|
|
104
|
+
':neqi': (v) => (isTargetMongo ? Not(new RegExp(`^${escapeRegExp(val(v))}$`, 'i')) : Not(ILike(v))),
|
|
105
|
+
':like': (v) => Like(`${val(v)}`),
|
|
106
|
+
':contains': (v) => Like(`%${val(v)}%`),
|
|
107
|
+
':ncontains': (v) => Not(Like(`%${val(v)}%`)),
|
|
108
|
+
':starts': (v) => Like(`${val(v)}%`),
|
|
109
|
+
':ends': (v) => Like(`%${val(v)}`),
|
|
110
|
+
':eq': (v) => {
|
|
111
|
+
const typedValue = typecastValue(v)
|
|
112
|
+
if (typedValue === null) return IsNull()
|
|
113
|
+
return isTargetMongo ? typedValue : Equal(typedValue)
|
|
114
|
+
},
|
|
115
|
+
':neq': (v) => Not(Equal(typecastValue(v))),
|
|
116
|
+
':gt': (v) => MoreThan(v),
|
|
117
|
+
':ge': (v) => MoreThanOrEqual(v),
|
|
118
|
+
':lt': (v) => LessThan(v),
|
|
119
|
+
':le': (v) => LessThanOrEqual(v),
|
|
120
|
+
':between': (v) => {
|
|
121
|
+
const s = v?.split(':')
|
|
122
|
+
return s?.length == 2 ? Between(s[0], s[1]) : v
|
|
123
|
+
},
|
|
124
|
+
':overlap': (v) => {
|
|
125
|
+
const values = val(v).split(',').map(typecastValue)
|
|
126
|
+
if (isTargetMongo) {
|
|
127
|
+
return { $in: values }
|
|
128
|
+
}
|
|
129
|
+
return Raw((alias) => `${alias} && ARRAY[:...overlapValues]::text[]`, { overlapValues: values })
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (yn(process.env.VOLCANIC_CUSTOM_QUERY_OPERATORS, false)) {
|
|
134
|
+
log.warn('Volcanic-TypeORM: Custom query operators (:raw) enabled. SECURITY RISK!')
|
|
135
|
+
reservedOperators[':raw'] = (v) => Raw((alias) => `${alias} ${v}`)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const reservedWords = Object.keys(reservedOperators).join('|')
|
|
139
|
+
const aliasRegex = /\[([^\]]+)\]$/
|
|
140
|
+
|
|
141
|
+
const allConditions = {}
|
|
142
|
+
|
|
143
|
+
for (const rawKey in where) {
|
|
144
|
+
let alias = ''
|
|
145
|
+
let key = rawKey
|
|
146
|
+
if (hasProtoRisk(rawKey)) {
|
|
147
|
+
continue
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const aliasMatch = rawKey.match(aliasRegex)
|
|
151
|
+
if (aliasMatch) {
|
|
152
|
+
alias = aliasMatch[1]
|
|
153
|
+
key = rawKey.replace(aliasRegex, '')
|
|
154
|
+
} else {
|
|
155
|
+
alias = key
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const m = key.match(new RegExp(`(${reservedWords})\\b`, 'ig'))
|
|
159
|
+
const operator = m?.length ? m[0] : ':eq'
|
|
160
|
+
const fullPath = key.replace(operator, '')
|
|
161
|
+
|
|
162
|
+
if (!isValidIdentifier(fullPath)) {
|
|
163
|
+
log.warn(`Volcanic-TypeORM: Invalid filter field skipped: ${fullPath}`)
|
|
164
|
+
continue
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const parts = fullPath.split('.')
|
|
168
|
+
|
|
169
|
+
if (sensitiveFields.some((field) => fullPath.includes(field))) {
|
|
170
|
+
continue
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let value = where[rawKey]
|
|
174
|
+
if (operator && reservedOperators[operator]) {
|
|
175
|
+
value = reservedOperators[operator](value)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
let condition = {}
|
|
179
|
+
let target = condition
|
|
180
|
+
while (parts.length > 1) {
|
|
181
|
+
const part: string = parts.shift() || ''
|
|
182
|
+
if (hasProtoRisk(part)) {
|
|
183
|
+
break
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
target = target[part] = target[part] || {}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const finalFieldName = parts[0]
|
|
190
|
+
if (!hasProtoRisk(finalFieldName)) {
|
|
191
|
+
target[finalFieldName] = value
|
|
192
|
+
aliasMap.set(alias, condition)
|
|
193
|
+
Object.assign(allConditions, condition)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return { allConditions, aliasMap }
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function applyQuery(data, extraWhere, repo) {
|
|
201
|
+
const { page: p = 1, pageSize = 25, skip: sk = 0, take: tk = 0, sort: s, _logic, ...where } = data
|
|
202
|
+
const page: number = (p < 1 ? 1 : p) - 1
|
|
203
|
+
const take: number = tk || pageSize
|
|
204
|
+
const skip: number = sk || page * pageSize
|
|
205
|
+
const order: string[] = !Array.isArray(s) ? [s] : s
|
|
206
|
+
|
|
207
|
+
const query = {} as {
|
|
208
|
+
skip?: number
|
|
209
|
+
take?: number
|
|
210
|
+
order?: object
|
|
211
|
+
where?: object | object[]
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (skip) query.skip = skip
|
|
215
|
+
if (take) query.take = take
|
|
216
|
+
if (order) query.order = useOrder(order)
|
|
217
|
+
|
|
218
|
+
const { allConditions, aliasMap } = useWhere(where, repo)
|
|
219
|
+
|
|
220
|
+
if (_logic) {
|
|
221
|
+
try {
|
|
222
|
+
const ast = parseLogicExpression(_logic)
|
|
223
|
+
query.where = buildWhereFromAst(ast, aliasMap, isMongo(repo))
|
|
224
|
+
} catch (e) {
|
|
225
|
+
console.error('Volcanic-TypeORM: Error parsing _logic parameter.', e)
|
|
226
|
+
query.where = allConditions
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
query.where = allConditions
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (extraWhere) {
|
|
233
|
+
const { allConditions: extraConditions } = useWhere(extraWhere, repo)
|
|
234
|
+
if (query.where && Object.keys(query.where).length > 0) {
|
|
235
|
+
if (isMongo(repo)) {
|
|
236
|
+
query.where = { $and: [query.where, extraConditions] }
|
|
237
|
+
} else {
|
|
238
|
+
if (Array.isArray(query.where)) {
|
|
239
|
+
query.where = query.where.map((condition) => ({
|
|
240
|
+
...condition,
|
|
241
|
+
...extraConditions
|
|
242
|
+
}))
|
|
243
|
+
} else {
|
|
244
|
+
query.where = { ...query.where, ...extraConditions }
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
} else {
|
|
248
|
+
query.where = extraConditions
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return query
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export async function executeFindQuery(
|
|
256
|
+
repo: any,
|
|
257
|
+
relations: any = {},
|
|
258
|
+
data: any = {},
|
|
259
|
+
extraWhere: any = {},
|
|
260
|
+
extraOptions: any = {}
|
|
261
|
+
) {
|
|
262
|
+
const extra = applyQuery(data, extraWhere, repo)
|
|
263
|
+
|
|
264
|
+
const [records = [], totalCount] = await repo.findAndCount({
|
|
265
|
+
relations: relations,
|
|
266
|
+
...extra,
|
|
267
|
+
...extraOptions
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
return {
|
|
271
|
+
records,
|
|
272
|
+
headers: {
|
|
273
|
+
'v-count': records.length,
|
|
274
|
+
'v-total': totalCount,
|
|
275
|
+
'v-page': data.page || 1,
|
|
276
|
+
'v-pageSize': extra.take,
|
|
277
|
+
'v-pageCount': Math.ceil(extra.take ? totalCount / extra.take : 1)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export async function executeFindView(
|
|
283
|
+
viewEntity: any,
|
|
284
|
+
data: any = {},
|
|
285
|
+
extraWhere: any = {},
|
|
286
|
+
extraOptions: any = {},
|
|
287
|
+
runner?: QueryRunner
|
|
288
|
+
) {
|
|
289
|
+
const extra = applyQuery(data, extraWhere, null)
|
|
290
|
+
const manager = runner ? runner.manager : global.connection.manager
|
|
291
|
+
|
|
292
|
+
const [records = [], totalCount] = await manager.findAndCount(viewEntity, {
|
|
293
|
+
...extra,
|
|
294
|
+
...extraOptions
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
return {
|
|
298
|
+
records,
|
|
299
|
+
headers: {
|
|
300
|
+
'v-count': records.length,
|
|
301
|
+
'v-total': totalCount,
|
|
302
|
+
'v-page': data.page || 1,
|
|
303
|
+
'v-pageSize': extra.take,
|
|
304
|
+
'v-pageCount': Math.ceil(extra.take ? totalCount / extra.take : 1)
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export async function executeCountQuery(repo: any, data = {}, extraWhere: any = {}) {
|
|
310
|
+
const { where = {} } = applyQuery(data, extraWhere, repo)
|
|
311
|
+
return await repo.count(isMongo(repo) ? where : { where: where })
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export async function executeCountView(viewEntity: any, data = {}, extraWhere: any = {}, runner?: QueryRunner) {
|
|
315
|
+
const { where = {} } = applyQuery(data, extraWhere, null)
|
|
316
|
+
const manager = runner ? runner.manager : global.connection.manager
|
|
317
|
+
return await manager.count(viewEntity, { where: where })
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function getType(repo) {
|
|
321
|
+
return repo?.manager?.connection?.options?.type || 'pg'
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function isMongo(repo) {
|
|
325
|
+
return getType(repo) === 'mongodb'
|
|
326
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as crypto from 'crypto'
|
|
2
|
+
|
|
3
|
+
const ALGORITHM_NEW = 'aes-256-gcm'
|
|
4
|
+
const ALGORITHM_OLD = 'aes-256-cbc'
|
|
5
|
+
const SECRET_KEY = process.env.MFA_DB_SECRET || process.env.JWT_SECRET
|
|
6
|
+
const IV_LENGTH_NEW = 12
|
|
7
|
+
|
|
8
|
+
function getKey() {
|
|
9
|
+
if (!SECRET_KEY) {
|
|
10
|
+
throw new Error('Secret key is not defined in environment variables.')
|
|
11
|
+
}
|
|
12
|
+
return crypto.createHash('sha256').update(String(SECRET_KEY)).digest('base64').substring(0, 32)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function encrypt(text: string): string {
|
|
16
|
+
if (!text) return text
|
|
17
|
+
const iv = crypto.randomBytes(IV_LENGTH_NEW)
|
|
18
|
+
const cipher = crypto.createCipheriv(ALGORITHM_NEW, Buffer.from(getKey()), iv)
|
|
19
|
+
let encrypted = cipher.update(text, 'utf8')
|
|
20
|
+
encrypted = Buffer.concat([encrypted, cipher.final()])
|
|
21
|
+
const authTag = cipher.getAuthTag()
|
|
22
|
+
return iv.toString('hex') + ':' + authTag.toString('hex') + ':' + encrypted.toString('hex')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function decrypt(text: string): string {
|
|
26
|
+
if (!text) return text
|
|
27
|
+
const textParts = text.split(':')
|
|
28
|
+
|
|
29
|
+
if (textParts.length === 2) {
|
|
30
|
+
const iv = Buffer.from(textParts[0], 'hex')
|
|
31
|
+
const encryptedText = Buffer.from(textParts[1], 'hex')
|
|
32
|
+
const decipher = crypto.createDecipheriv(ALGORITHM_OLD, Buffer.from(getKey()), iv)
|
|
33
|
+
let decrypted = decipher.update(encryptedText)
|
|
34
|
+
decrypted = Buffer.concat([decrypted, decipher.final()])
|
|
35
|
+
return decrypted.toString()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (textParts.length === 3) {
|
|
39
|
+
const iv = Buffer.from(textParts[0], 'hex')
|
|
40
|
+
const authTag = Buffer.from(textParts[1], 'hex')
|
|
41
|
+
const encryptedText = Buffer.from(textParts[2], 'hex')
|
|
42
|
+
|
|
43
|
+
const decipher = crypto.createDecipheriv(ALGORITHM_NEW, Buffer.from(getKey()), iv)
|
|
44
|
+
decipher.setAuthTag(authTag)
|
|
45
|
+
|
|
46
|
+
let decrypted = decipher.update(encryptedText, undefined, 'utf8')
|
|
47
|
+
decrypted += decipher.final('utf8')
|
|
48
|
+
return decrypted
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return text
|
|
52
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function trace(data) {
|
|
2
|
+
if (global.isLoggingEnabled && global.log?.trace) {
|
|
3
|
+
global.log.trace(data)
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function debug(data) {
|
|
8
|
+
if (global.isLoggingEnabled && global.log?.debug) {
|
|
9
|
+
global.log.debug(data)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function info(data) {
|
|
14
|
+
if (global.isLoggingEnabled && global.log?.info) {
|
|
15
|
+
global.log.info(data)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function warn(data) {
|
|
20
|
+
if (global.isLoggingEnabled && global.log?.warn) {
|
|
21
|
+
global.log.warn(data)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function error(data) {
|
|
26
|
+
if (global.isLoggingEnabled && global.log?.error) {
|
|
27
|
+
global.log.error(data)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function fatal(data) {
|
|
32
|
+
if (global.isLoggingEnabled && global.log?.fatal) {
|
|
33
|
+
global.log.fatal(data)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
export default function yn(value: any, defaultValue: boolean): boolean {
|
|
5
|
+
if (value === undefined || value === null) {
|
|
6
|
+
return defaultValue
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const val = String(value).trim()
|
|
10
|
+
|
|
11
|
+
if (/^(?:y|yes|true|1|on)$/i.test(val)) {
|
|
12
|
+
return true
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (/^(?:n|no|false|0|off)$/i.test(val)) {
|
|
16
|
+
return false
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return defaultValue || false
|
|
20
|
+
}
|