@flowerforce/flowerbase 1.0.1-beta.3
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/CHANGELOG.md +0 -0
- package/LICENSE +3 -0
- package/README.md +18 -0
- package/dist/auth/controller.d.ts +8 -0
- package/dist/auth/controller.d.ts.map +1 -0
- package/dist/auth/controller.js +76 -0
- package/dist/auth/dtos.d.ts +6 -0
- package/dist/auth/dtos.d.ts.map +1 -0
- package/dist/auth/dtos.js +2 -0
- package/dist/auth/plugins/jwt.d.ts +14 -0
- package/dist/auth/plugins/jwt.d.ts.map +1 -0
- package/dist/auth/plugins/jwt.js +68 -0
- package/dist/auth/providers/local-userpass/controller.d.ts +8 -0
- package/dist/auth/providers/local-userpass/controller.d.ts.map +1 -0
- package/dist/auth/providers/local-userpass/controller.js +184 -0
- package/dist/auth/providers/local-userpass/dtos.d.ts +35 -0
- package/dist/auth/providers/local-userpass/dtos.d.ts.map +1 -0
- package/dist/auth/providers/local-userpass/dtos.js +2 -0
- package/dist/auth/utils.d.ts +126 -0
- package/dist/auth/utils.d.ts.map +1 -0
- package/dist/auth/utils.js +122 -0
- package/dist/constants.d.ts +18 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +34 -0
- package/dist/features/endpoints/index.d.ts +10 -0
- package/dist/features/endpoints/index.d.ts.map +1 -0
- package/dist/features/endpoints/index.js +31 -0
- package/dist/features/endpoints/interface.d.ts +27 -0
- package/dist/features/endpoints/interface.d.ts.map +1 -0
- package/dist/features/endpoints/interface.js +2 -0
- package/dist/features/endpoints/utils.d.ts +31 -0
- package/dist/features/endpoints/utils.d.ts.map +1 -0
- package/dist/features/endpoints/utils.js +85 -0
- package/dist/features/functions/controller.d.ts +9 -0
- package/dist/features/functions/controller.d.ts.map +1 -0
- package/dist/features/functions/controller.js +88 -0
- package/dist/features/functions/dtos.d.ts +34 -0
- package/dist/features/functions/dtos.d.ts.map +1 -0
- package/dist/features/functions/dtos.js +2 -0
- package/dist/features/functions/index.d.ts +9 -0
- package/dist/features/functions/index.d.ts.map +1 -0
- package/dist/features/functions/index.js +28 -0
- package/dist/features/functions/interface.d.ts +32 -0
- package/dist/features/functions/interface.d.ts.map +1 -0
- package/dist/features/functions/interface.js +2 -0
- package/dist/features/functions/utils.d.ts +23 -0
- package/dist/features/functions/utils.d.ts.map +1 -0
- package/dist/features/functions/utils.js +75 -0
- package/dist/features/rules/index.d.ts +1 -0
- package/dist/features/rules/index.d.ts.map +1 -0
- package/dist/features/rules/index.js +1 -0
- package/dist/features/rules/interface.d.ts +22 -0
- package/dist/features/rules/interface.d.ts.map +1 -0
- package/dist/features/rules/interface.js +2 -0
- package/dist/features/rules/utils.d.ts +3 -0
- package/dist/features/rules/utils.d.ts.map +1 -0
- package/dist/features/rules/utils.js +31 -0
- package/dist/features/triggers/dtos.d.ts +9 -0
- package/dist/features/triggers/dtos.d.ts.map +1 -0
- package/dist/features/triggers/dtos.js +2 -0
- package/dist/features/triggers/index.d.ts +10 -0
- package/dist/features/triggers/index.d.ts.map +1 -0
- package/dist/features/triggers/index.js +57 -0
- package/dist/features/triggers/interface.d.ts +44 -0
- package/dist/features/triggers/interface.d.ts.map +1 -0
- package/dist/features/triggers/interface.js +2 -0
- package/dist/features/triggers/utils.d.ts +16 -0
- package/dist/features/triggers/utils.d.ts.map +1 -0
- package/dist/features/triggers/utils.js +153 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/model.d.ts +2 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +2 -0
- package/dist/services/api/index.d.ts +36 -0
- package/dist/services/api/index.d.ts.map +1 -0
- package/dist/services/api/index.js +36 -0
- package/dist/services/api/model.d.ts +33 -0
- package/dist/services/api/model.d.ts.map +1 -0
- package/dist/services/api/model.js +2 -0
- package/dist/services/api/utils.d.ts +16 -0
- package/dist/services/api/utils.d.ts.map +1 -0
- package/dist/services/api/utils.js +45 -0
- package/dist/services/aws/index.d.ts +13 -0
- package/dist/services/aws/index.d.ts.map +1 -0
- package/dist/services/aws/index.js +50 -0
- package/dist/services/index.d.ts +41 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +14 -0
- package/dist/services/interface.d.ts +3 -0
- package/dist/services/interface.d.ts.map +1 -0
- package/dist/services/interface.js +2 -0
- package/dist/services/mongodb-atlas/index.d.ts +4 -0
- package/dist/services/mongodb-atlas/index.d.ts.map +1 -0
- package/dist/services/mongodb-atlas/index.js +483 -0
- package/dist/services/mongodb-atlas/model.d.ts +39 -0
- package/dist/services/mongodb-atlas/model.d.ts.map +1 -0
- package/dist/services/mongodb-atlas/model.js +2 -0
- package/dist/services/mongodb-atlas/utils.d.ts +8 -0
- package/dist/services/mongodb-atlas/utils.d.ts.map +1 -0
- package/dist/services/mongodb-atlas/utils.js +33 -0
- package/dist/state.d.ts +6 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +18 -0
- package/dist/utils/context/helpers.d.ts +74 -0
- package/dist/utils/context/helpers.d.ts.map +1 -0
- package/dist/utils/context/helpers.js +60 -0
- package/dist/utils/context/index.d.ts +14 -0
- package/dist/utils/context/index.d.ts.map +1 -0
- package/dist/utils/context/index.js +50 -0
- package/dist/utils/context/interface.d.ts +18 -0
- package/dist/utils/context/interface.d.ts.map +1 -0
- package/dist/utils/context/interface.js +2 -0
- package/dist/utils/crypto/index.d.ts +19 -0
- package/dist/utils/crypto/index.d.ts.map +1 -0
- package/dist/utils/crypto/index.js +50 -0
- package/dist/utils/helpers/someAsync.d.ts +12 -0
- package/dist/utils/helpers/someAsync.d.ts.map +1 -0
- package/dist/utils/helpers/someAsync.js +56 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +11 -0
- package/dist/utils/initializer/exposeRoutes.d.ts +8 -0
- package/dist/utils/initializer/exposeRoutes.d.ts.map +1 -0
- package/dist/utils/initializer/exposeRoutes.js +41 -0
- package/dist/utils/initializer/registerPlugins.d.ts +19 -0
- package/dist/utils/initializer/registerPlugins.d.ts.map +1 -0
- package/dist/utils/initializer/registerPlugins.js +84 -0
- package/dist/utils/roles/helpers.d.ts +4 -0
- package/dist/utils/roles/helpers.d.ts.map +1 -0
- package/dist/utils/roles/helpers.js +47 -0
- package/dist/utils/roles/interface.d.ts +33 -0
- package/dist/utils/roles/interface.d.ts.map +1 -0
- package/dist/utils/roles/interface.js +2 -0
- package/dist/utils/roles/machines/commonValidators.d.ts +6 -0
- package/dist/utils/roles/machines/commonValidators.d.ts.map +1 -0
- package/dist/utils/roles/machines/commonValidators.js +34 -0
- package/dist/utils/roles/machines/index.d.ts +14 -0
- package/dist/utils/roles/machines/index.d.ts.map +1 -0
- package/dist/utils/roles/machines/index.js +27 -0
- package/dist/utils/roles/machines/interface.d.ts +46 -0
- package/dist/utils/roles/machines/interface.d.ts.map +1 -0
- package/dist/utils/roles/machines/interface.js +2 -0
- package/dist/utils/roles/machines/machine.d.ts +15 -0
- package/dist/utils/roles/machines/machine.d.ts.map +1 -0
- package/dist/utils/roles/machines/machine.js +97 -0
- package/dist/utils/roles/machines/read/A/index.d.ts +3 -0
- package/dist/utils/roles/machines/read/A/index.d.ts.map +1 -0
- package/dist/utils/roles/machines/read/A/index.js +27 -0
- package/dist/utils/roles/machines/read/B/index.d.ts +3 -0
- package/dist/utils/roles/machines/read/B/index.d.ts.map +1 -0
- package/dist/utils/roles/machines/read/B/index.js +36 -0
- package/dist/utils/roles/machines/read/C/index.d.ts +3 -0
- package/dist/utils/roles/machines/read/C/index.d.ts.map +1 -0
- package/dist/utils/roles/machines/read/C/index.js +38 -0
- package/dist/utils/roles/machines/read/D/index.d.ts +3 -0
- package/dist/utils/roles/machines/read/D/index.d.ts.map +1 -0
- package/dist/utils/roles/machines/read/D/index.js +26 -0
- package/dist/utils/roles/machines/read/D/validators.d.ts +4 -0
- package/dist/utils/roles/machines/read/D/validators.d.ts.map +1 -0
- package/dist/utils/roles/machines/read/D/validators.js +24 -0
- package/dist/utils/roles/machines/read/index.d.ts +2 -0
- package/dist/utils/roles/machines/read/index.d.ts.map +1 -0
- package/dist/utils/roles/machines/read/index.js +8 -0
- package/dist/utils/roles/machines/utils.d.ts +37 -0
- package/dist/utils/roles/machines/utils.d.ts.map +1 -0
- package/dist/utils/roles/machines/utils.js +54 -0
- package/dist/utils/roles/machines/write/A/index.d.ts +3 -0
- package/dist/utils/roles/machines/write/A/index.d.ts.map +1 -0
- package/dist/utils/roles/machines/write/A/index.js +29 -0
- package/dist/utils/roles/machines/write/B/index.d.ts +3 -0
- package/dist/utils/roles/machines/write/B/index.d.ts.map +1 -0
- package/dist/utils/roles/machines/write/B/index.js +47 -0
- package/dist/utils/roles/machines/write/C/index.d.ts +3 -0
- package/dist/utils/roles/machines/write/C/index.d.ts.map +1 -0
- package/dist/utils/roles/machines/write/C/index.js +26 -0
- package/dist/utils/roles/machines/write/C/validators.d.ts +4 -0
- package/dist/utils/roles/machines/write/C/validators.d.ts.map +1 -0
- package/dist/utils/roles/machines/write/C/validators.js +24 -0
- package/dist/utils/roles/machines/write/index.d.ts +2 -0
- package/dist/utils/roles/machines/write/index.d.ts.map +1 -0
- package/dist/utils/roles/machines/write/index.js +7 -0
- package/dist/utils/rules-matcher/interface.d.ts +338 -0
- package/dist/utils/rules-matcher/interface.d.ts.map +1 -0
- package/dist/utils/rules-matcher/interface.js +26 -0
- package/dist/utils/rules-matcher/utils.d.ts +11 -0
- package/dist/utils/rules-matcher/utils.d.ts.map +1 -0
- package/dist/utils/rules-matcher/utils.js +214 -0
- package/dist/utils/rules.d.ts +2 -0
- package/dist/utils/rules.d.ts.map +1 -0
- package/dist/utils/rules.js +22 -0
- package/jest.config.ts +24 -0
- package/package.json +63 -0
- package/project.json +10 -0
- package/rollup.config.js +17 -0
- package/src/auth/controller.ts +78 -0
- package/src/auth/dtos.ts +6 -0
- package/src/auth/plugins/jwt.ts +68 -0
- package/src/auth/providers/local-userpass/controller.ts +226 -0
- package/src/auth/providers/local-userpass/dtos.ts +40 -0
- package/src/auth/utils.ts +165 -0
- package/src/babel.config.json +3 -0
- package/src/constants.ts +22 -0
- package/src/fastify.d.ts +28 -0
- package/src/features/endpoints/index.ts +27 -0
- package/src/features/endpoints/interface.ts +29 -0
- package/src/features/endpoints/utils.ts +72 -0
- package/src/features/functions/controller.ts +102 -0
- package/src/features/functions/dtos.ts +41 -0
- package/src/features/functions/index.ts +21 -0
- package/src/features/functions/interface.ts +38 -0
- package/src/features/functions/utils.ts +82 -0
- package/src/features/rules/index.tsx +0 -0
- package/src/features/rules/interface.ts +24 -0
- package/src/features/rules/utils.ts +20 -0
- package/src/features/triggers/dtos.ts +9 -0
- package/src/features/triggers/index.ts +34 -0
- package/src/features/triggers/interface.ts +44 -0
- package/src/features/triggers/utils.ts +157 -0
- package/src/global.d.ts +0 -0
- package/src/index.ts +75 -0
- package/src/model.ts +1 -0
- package/src/services/api/index.ts +50 -0
- package/src/services/api/model.ts +38 -0
- package/src/services/api/utils.ts +39 -0
- package/src/services/aws/index.ts +48 -0
- package/src/services/index.ts +9 -0
- package/src/services/interface.ts +3 -0
- package/src/services/mongodb-atlas/index.ts +569 -0
- package/src/services/mongodb-atlas/model.ts +67 -0
- package/src/services/mongodb-atlas/utils.ts +44 -0
- package/src/state.ts +24 -0
- package/src/utils/__tests__/STEP_A_STATES.test.ts +54 -0
- package/src/utils/__tests__/STEP_B_STATES.test.ts +113 -0
- package/src/utils/__tests__/STEP_C_STATES.test.ts +87 -0
- package/src/utils/__tests__/STEP_D_STATES.test.ts +93 -0
- package/src/utils/__tests__/checkAdditionalFieldsFn.test.ts +45 -0
- package/src/utils/__tests__/checkApplyWhen.test.ts +49 -0
- package/src/utils/__tests__/checkFieldsPropertyExists.test.ts +47 -0
- package/src/utils/__tests__/checkIsValidFieldNameFn.test.ts +190 -0
- package/src/utils/__tests__/comparePassword.test.ts +38 -0
- package/src/utils/__tests__/evaluateDocumentsFiltersReadFn.test.ts +57 -0
- package/src/utils/__tests__/evaluateDocumentsFiltersWriteFn.test.ts +57 -0
- package/src/utils/__tests__/evaluateTopLevelReadFn.test.ts +58 -0
- package/src/utils/__tests__/evaluateTopLevelWriteFn.test.ts +66 -0
- package/src/utils/__tests__/exposeRoutes.test.ts +65 -0
- package/src/utils/__tests__/generateContextData.test.ts +75 -0
- package/src/utils/__tests__/getDefaultRule.test.ts +29 -0
- package/src/utils/__tests__/getKey.test.ts +12 -0
- package/src/utils/__tests__/getKeys.test.ts +11 -0
- package/src/utils/__tests__/getWinningRole.test.ts +66 -0
- package/src/utils/__tests__/hashPassword.test.ts +28 -0
- package/src/utils/__tests__/isEmpty.test.ts +17 -0
- package/src/utils/__tests__/logMachineInfo.test.ts +15 -0
- package/src/utils/__tests__/operators.test.ts +99 -0
- package/src/utils/__tests__/readFileContent.test.ts +35 -0
- package/src/utils/__tests__/registerPlugins.test.ts +59 -0
- package/src/utils/__tests__/rule.test.ts +51 -0
- package/src/utils/__tests__/rulesMatcherInterfaces.test.ts +57 -0
- package/src/utils/__tests__/rulesMatcherUtils.test.ts +56 -0
- package/src/utils/__tests__/someAsync.test.ts +55 -0
- package/src/utils/context/helpers.ts +71 -0
- package/src/utils/context/index.ts +52 -0
- package/src/utils/context/interface.ts +19 -0
- package/src/utils/crypto/index.ts +36 -0
- package/src/utils/helpers/someAsync.ts +24 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/initializer/exposeRoutes.ts +26 -0
- package/src/utils/initializer/registerPlugins.ts +97 -0
- package/src/utils/roles/helpers.ts +47 -0
- package/src/utils/roles/interface.ts +42 -0
- package/src/utils/roles/machines/commonValidators.ts +24 -0
- package/src/utils/roles/machines/index.ts +20 -0
- package/src/utils/roles/machines/interface.ts +46 -0
- package/src/utils/roles/machines/machine.ts +85 -0
- package/src/utils/roles/machines/read/A/index.ts +19 -0
- package/src/utils/roles/machines/read/B/index.ts +31 -0
- package/src/utils/roles/machines/read/C/index.ts +30 -0
- package/src/utils/roles/machines/read/D/index.ts +20 -0
- package/src/utils/roles/machines/read/D/validators.ts +24 -0
- package/src/utils/roles/machines/read/index.ts +6 -0
- package/src/utils/roles/machines/utils.ts +54 -0
- package/src/utils/roles/machines/write/A/index.ts +25 -0
- package/src/utils/roles/machines/write/B/index.ts +43 -0
- package/src/utils/roles/machines/write/C/index.ts +20 -0
- package/src/utils/roles/machines/write/C/validators.ts +24 -0
- package/src/utils/roles/machines/write/index.ts +5 -0
- package/src/utils/rules-matcher/interface.ts +365 -0
- package/src/utils/rules-matcher/utils.ts +281 -0
- package/src/utils/rules.ts +19 -0
- package/tsconfig.json +28 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import sendGrid from "@sendgrid/mail"
|
|
2
|
+
import { FastifyInstance } from 'fastify'
|
|
3
|
+
import { AUTH_CONFIG, DB_NAME } from '../../../constants'
|
|
4
|
+
import { StateManager } from "../../../state"
|
|
5
|
+
import { GenerateContext } from "../../../utils/context"
|
|
6
|
+
import { comparePassword, generateToken, hashPassword } from '../../../utils/crypto'
|
|
7
|
+
import {
|
|
8
|
+
AUTH_ENDPOINTS,
|
|
9
|
+
AUTH_ERRORS,
|
|
10
|
+
CONFIRM_RESET_SCHEMA,
|
|
11
|
+
getMailConfig,
|
|
12
|
+
LOGIN_SCHEMA,
|
|
13
|
+
PROVIDER_TYPE,
|
|
14
|
+
REGISTRATION_SCHEMA,
|
|
15
|
+
RESET_SCHEMA
|
|
16
|
+
} from '../../utils'
|
|
17
|
+
import { ConfirmResetPasswordDto, LoginDto, RegistrationDto, ResetPasswordDto } from './dtos'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Controller for handling local user registration and login.
|
|
21
|
+
* @testable
|
|
22
|
+
* @param {FastifyInstance} app - The Fastify instance.
|
|
23
|
+
*/
|
|
24
|
+
export async function localUserPassController(app: FastifyInstance) {
|
|
25
|
+
const { authCollection } = AUTH_CONFIG
|
|
26
|
+
const db = app.mongo.client.db(DB_NAME)
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Endpoint for user registration.
|
|
30
|
+
*
|
|
31
|
+
* @route {POST} /register
|
|
32
|
+
* @param {RegistrationDto} req - The request object with registration data.
|
|
33
|
+
* @param {FastifyReply} res - The response object.
|
|
34
|
+
* @returns {Promise<Object>} A promise resolving with the newly created user's ID.
|
|
35
|
+
*/
|
|
36
|
+
app.post<RegistrationDto>(
|
|
37
|
+
AUTH_ENDPOINTS.REGISTRATION,
|
|
38
|
+
{
|
|
39
|
+
schema: REGISTRATION_SCHEMA
|
|
40
|
+
},
|
|
41
|
+
async function (req, res) {
|
|
42
|
+
const { email, password } = req.body
|
|
43
|
+
const hashedPassword = await hashPassword(password)
|
|
44
|
+
|
|
45
|
+
const existingUser = await db.collection(authCollection!).findOne({
|
|
46
|
+
email
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
if (existingUser) {
|
|
50
|
+
res.status(409)
|
|
51
|
+
return {
|
|
52
|
+
error: 'This email address is already used'
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const result = await db.collection(authCollection!).insertOne({
|
|
57
|
+
email: email,
|
|
58
|
+
password: hashedPassword,
|
|
59
|
+
custom_data: {
|
|
60
|
+
// todo li faremo arrivare
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
await db?.collection(authCollection!).updateOne(
|
|
65
|
+
{
|
|
66
|
+
email: email
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
$set: {
|
|
70
|
+
identities: [
|
|
71
|
+
{
|
|
72
|
+
id: result?.insertedId.toString(),
|
|
73
|
+
provider_id: result?.insertedId.toString(),
|
|
74
|
+
provider_type: PROVIDER_TYPE,
|
|
75
|
+
provider_data: { email }
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
res.status(201)
|
|
83
|
+
return {
|
|
84
|
+
userId: result?.insertedId
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Endpoint for user login.
|
|
91
|
+
*
|
|
92
|
+
* @route {POST} /login
|
|
93
|
+
* @param {LoginDto} req - The request object with login data.
|
|
94
|
+
* @returns {Promise<Object>} A promise resolving with access and refresh tokens.
|
|
95
|
+
*/
|
|
96
|
+
app.post<LoginDto>(
|
|
97
|
+
AUTH_ENDPOINTS.LOGIN,
|
|
98
|
+
{
|
|
99
|
+
schema: LOGIN_SCHEMA
|
|
100
|
+
},
|
|
101
|
+
async function (req) {
|
|
102
|
+
|
|
103
|
+
const storedUser = await db.collection(authCollection!).findOne({
|
|
104
|
+
email: req.body.username
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
if (!storedUser) {
|
|
108
|
+
throw new Error(AUTH_ERRORS.INVALID_CREDENTIALS)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const passwordMatches = await comparePassword(
|
|
112
|
+
req.body.password,
|
|
113
|
+
storedUser.password
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
if (!passwordMatches) {
|
|
117
|
+
throw new Error(AUTH_ERRORS.INVALID_CREDENTIALS)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
access_token: this.createAccessToken(storedUser),
|
|
122
|
+
refresh_token: this.createRefreshToken(storedUser),
|
|
123
|
+
device_id: '',
|
|
124
|
+
user_id: storedUser._id.toString()
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Endpoint for reset password.
|
|
131
|
+
*
|
|
132
|
+
* @route {POST} /reset/call
|
|
133
|
+
* @param {ResetPasswordDto} req - The request object with th reset request.
|
|
134
|
+
* @returns {Promise<void>}
|
|
135
|
+
*/
|
|
136
|
+
app.post<ResetPasswordDto>(
|
|
137
|
+
AUTH_ENDPOINTS.RESET,
|
|
138
|
+
{
|
|
139
|
+
schema: RESET_SCHEMA
|
|
140
|
+
},
|
|
141
|
+
async function (req) {
|
|
142
|
+
const { resetPasswordCollection, resetPasswordConfig } = AUTH_CONFIG
|
|
143
|
+
const email = req.body.email
|
|
144
|
+
const storedUser = await db.collection(authCollection!).findOne({
|
|
145
|
+
email
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
if (!storedUser) {
|
|
149
|
+
throw new Error(AUTH_ERRORS.INVALID_CREDENTIALS)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const token = generateToken()
|
|
153
|
+
const tokenId = generateToken()
|
|
154
|
+
|
|
155
|
+
await db?.collection(resetPasswordCollection).updateOne(
|
|
156
|
+
{ email },
|
|
157
|
+
{ $set: { token, tokenId, email, createdAt: new Date() } },
|
|
158
|
+
{ upsert: true }
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
if (resetPasswordConfig.runResetFunction && resetPasswordConfig.resetFunctionName) {
|
|
163
|
+
const functionsList = StateManager.select("functions")
|
|
164
|
+
const services = StateManager.select("services")
|
|
165
|
+
const currentFunction = functionsList[resetPasswordConfig.resetFunctionName]
|
|
166
|
+
await GenerateContext({
|
|
167
|
+
args: [{ token, tokenId, email }],
|
|
168
|
+
app,
|
|
169
|
+
rules: {},
|
|
170
|
+
user: {},
|
|
171
|
+
currentFunction,
|
|
172
|
+
functionsList,
|
|
173
|
+
services
|
|
174
|
+
})
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const { from, subject, mailToken, body } = getMailConfig(resetPasswordConfig, token, tokenId)
|
|
179
|
+
sendGrid.setApiKey(mailToken)
|
|
180
|
+
await sendGrid.send({
|
|
181
|
+
to: email,
|
|
182
|
+
from,
|
|
183
|
+
subject,
|
|
184
|
+
html: body
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
}
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Endpoint for confirm reset password.
|
|
192
|
+
*
|
|
193
|
+
* @route {POST} /reset
|
|
194
|
+
* @param {ConfirmResetPasswordDto} req - The request object with reset data.
|
|
195
|
+
* @returns {Promise<void>}
|
|
196
|
+
*/
|
|
197
|
+
app.post<ConfirmResetPasswordDto>(
|
|
198
|
+
AUTH_ENDPOINTS.CONFIRM_RESET,
|
|
199
|
+
{
|
|
200
|
+
schema: CONFIRM_RESET_SCHEMA
|
|
201
|
+
},
|
|
202
|
+
async function (req) {
|
|
203
|
+
const { resetPasswordCollection } = AUTH_CONFIG
|
|
204
|
+
const { token, tokenId, password } = req.body
|
|
205
|
+
|
|
206
|
+
const resetRequest = await db?.collection(resetPasswordCollection).findOne(
|
|
207
|
+
{ token, tokenId },
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
if (!resetRequest) {
|
|
211
|
+
throw new Error(AUTH_ERRORS.INVALID_RESET_PARAMS)
|
|
212
|
+
}
|
|
213
|
+
const hashedPassword = await hashPassword(password)
|
|
214
|
+
await db.collection(authCollection!).updateOne({ email: resetRequest.email, }, {
|
|
215
|
+
$set: {
|
|
216
|
+
password: hashedPassword
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
await db?.collection(resetPasswordCollection).deleteOne(
|
|
221
|
+
{ _id: resetRequest._id },
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
}
|
|
225
|
+
)
|
|
226
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type RegisterUserDto = {
|
|
2
|
+
email: string
|
|
3
|
+
password: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type LoginUserDto = {
|
|
7
|
+
username: string
|
|
8
|
+
password: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type LoginSuccessDto = {
|
|
12
|
+
access_token: string
|
|
13
|
+
device_id: string
|
|
14
|
+
refresh_token: string
|
|
15
|
+
user_id: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RegistrationDto {
|
|
19
|
+
Body: RegisterUserDto
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface LoginDto {
|
|
23
|
+
Body: LoginUserDto
|
|
24
|
+
Reply: LoginSuccessDto
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ResetPasswordDto {
|
|
28
|
+
Body: {
|
|
29
|
+
email: string
|
|
30
|
+
password: string
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ConfirmResetPasswordDto {
|
|
35
|
+
Body: {
|
|
36
|
+
token: string
|
|
37
|
+
tokenId: string
|
|
38
|
+
password: string
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
|
|
3
|
+
export const LOGIN_SCHEMA = {
|
|
4
|
+
body: {
|
|
5
|
+
type: 'object',
|
|
6
|
+
properties: {
|
|
7
|
+
username: { type: 'string' },
|
|
8
|
+
password: { type: 'string' }
|
|
9
|
+
},
|
|
10
|
+
required: ['username', 'password']
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const RESET_SCHEMA = {
|
|
15
|
+
body: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
email: { type: 'string' },
|
|
19
|
+
password: { type: 'string' }
|
|
20
|
+
},
|
|
21
|
+
required: ['email', 'password']
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
export const CONFIRM_RESET_SCHEMA = {
|
|
27
|
+
body: {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
password: { type: 'string' },
|
|
31
|
+
token: { type: 'string' },
|
|
32
|
+
tokenId: { type: 'string' }
|
|
33
|
+
},
|
|
34
|
+
required: ['password', 'token', 'tokenId']
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
export const REGISTRATION_SCHEMA = {
|
|
40
|
+
body: {
|
|
41
|
+
type: 'object',
|
|
42
|
+
properties: {
|
|
43
|
+
email: { type: 'string' },
|
|
44
|
+
password: { type: 'string' }
|
|
45
|
+
},
|
|
46
|
+
required: ['email', 'password']
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export enum AUTH_ENDPOINTS {
|
|
51
|
+
LOGIN = '/login',
|
|
52
|
+
REGISTRATION = '/register',
|
|
53
|
+
PROFILE = '/profile',
|
|
54
|
+
SESSION = '/session',
|
|
55
|
+
RESET = '/reset/call',
|
|
56
|
+
CONFIRM_RESET = "/reset"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export enum AUTH_ERRORS {
|
|
60
|
+
INVALID_CREDENTIALS = 'Invalid credentials',
|
|
61
|
+
INVALID_TOKEN = 'Invalid refresh token provided',
|
|
62
|
+
INVALID_RESET_PARAMS = 'Invalid token or tokenId provided'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface AuthConfig {
|
|
66
|
+
auth_collection?: string
|
|
67
|
+
'api-key': ApiKey
|
|
68
|
+
'local-userpass': LocalUserpass
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface ApiKey {
|
|
72
|
+
name: string
|
|
73
|
+
type: string
|
|
74
|
+
disabled: boolean
|
|
75
|
+
}
|
|
76
|
+
interface LocalUserpass {
|
|
77
|
+
name: string
|
|
78
|
+
type: string
|
|
79
|
+
disabled: boolean
|
|
80
|
+
config: Config
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface Config {
|
|
84
|
+
autoConfirm: boolean
|
|
85
|
+
resetFunctionName: string
|
|
86
|
+
resetPasswordUrl: string
|
|
87
|
+
runConfirmationFunction: boolean
|
|
88
|
+
runResetFunction: boolean
|
|
89
|
+
mailConfig: {
|
|
90
|
+
from: string
|
|
91
|
+
subject: string
|
|
92
|
+
mailToken: string
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface CustomUserDataConfig {
|
|
97
|
+
enabled: boolean
|
|
98
|
+
mongo_service_name: string
|
|
99
|
+
database_name: string
|
|
100
|
+
collection_name: string
|
|
101
|
+
user_id_field: string
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const PROVIDER_TYPE = 'local-userpass'
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* > Loads the auth config json file
|
|
108
|
+
* @testable
|
|
109
|
+
*/
|
|
110
|
+
export const loadAuthConfig = (): AuthConfig => {
|
|
111
|
+
return JSON.parse(fs.readFileSync('auth/providers.json', 'utf-8'))
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* > Loads the custom user data config json file
|
|
116
|
+
* @testable
|
|
117
|
+
*/
|
|
118
|
+
export const loadCustomUserData = (): CustomUserDataConfig => {
|
|
119
|
+
return JSON.parse(fs.readFileSync('auth/custom_user_data.json', 'utf-8'))
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
export const getMailConfig = (resetPasswordConfig: Config, token: string, tokenId: string) => {
|
|
125
|
+
const { mailConfig, resetPasswordUrl } = resetPasswordConfig
|
|
126
|
+
const ENV_PREFIX = "ENV"
|
|
127
|
+
const { from, subject, mailToken } = mailConfig
|
|
128
|
+
|
|
129
|
+
const [fromPrefix, fromPath] = from.split(".")
|
|
130
|
+
const currentSender = (fromPrefix === ENV_PREFIX ? process.env[fromPath] : from) ?? ""
|
|
131
|
+
const [subjectPrefix, subjectPath] = subject.split(".")
|
|
132
|
+
const currentSubject = (subjectPrefix === ENV_PREFIX ? process.env[subjectPath] : subject) ?? ""
|
|
133
|
+
const [mailTokenPrefix, mailTokenPath] = mailToken.split(".")
|
|
134
|
+
const currentMailToken = (mailTokenPrefix === "ENV" ? process.env[mailTokenPath] : mailToken) ?? ""
|
|
135
|
+
|
|
136
|
+
const link = `${resetPasswordUrl}/${token}/${tokenId}`;
|
|
137
|
+
const body = `<body style="font-family: Arial, sans-serif; background-color: #f4f4f4; text-align: center; padding: 20px;">
|
|
138
|
+
<table width="100%" cellspacing="0" cellpadding="0">
|
|
139
|
+
<tr>
|
|
140
|
+
<td align="center">
|
|
141
|
+
<table width="600" cellspacing="0" cellpadding="0" style="background: #ffffff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);">
|
|
142
|
+
<tr>
|
|
143
|
+
<td align="center">
|
|
144
|
+
<h2>Password Reset Request</h2>
|
|
145
|
+
<p>If you requested a password reset, click the button below to reset your password.</p>
|
|
146
|
+
<p>If you did not request this, please ignore this email.</p>
|
|
147
|
+
<p>
|
|
148
|
+
<a href="${link}" style="display: inline-block; padding: 12px 20px; font-size: 16px; color: #ffffff; background: #007bff; text-decoration: none; border-radius: 5px;">Reset Password</a>
|
|
149
|
+
</p>
|
|
150
|
+
<p style="margin-top: 20px; font-size: 12px; color: #777;">If the button does not work, copy and paste the following link into your browser:</p>
|
|
151
|
+
<p style="font-size: 12px; color: #777;">${link}</p>
|
|
152
|
+
</td>
|
|
153
|
+
</tr>
|
|
154
|
+
</table>
|
|
155
|
+
</td>
|
|
156
|
+
</tr>
|
|
157
|
+
</table>
|
|
158
|
+
</body>`
|
|
159
|
+
return {
|
|
160
|
+
from: currentSender ?? "",
|
|
161
|
+
subject: currentSubject,
|
|
162
|
+
mailToken: currentMailToken,
|
|
163
|
+
body
|
|
164
|
+
}
|
|
165
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { loadAuthConfig, loadCustomUserData } from './auth/utils'
|
|
2
|
+
|
|
3
|
+
const { database_name, collection_name = 'users', user_id_field = "id" } = loadCustomUserData()
|
|
4
|
+
const { auth_collection = 'auth_users', ...configuration } = loadAuthConfig()
|
|
5
|
+
|
|
6
|
+
export const DEFAULT_CONFIG = {
|
|
7
|
+
PORT: Number(process.env.PORT) || 3000,
|
|
8
|
+
MONGODB_URL: process.env.MONGODB_URL || '',
|
|
9
|
+
JWT_SECRET: process.env.JWT_SECRET || '',
|
|
10
|
+
API_VERSION: process.env.API_VERSION || "v2.0",
|
|
11
|
+
HTTPS_SCHEMA: process.env.HTTPS_SCHEMA || 'https'
|
|
12
|
+
}
|
|
13
|
+
export const API_VERSION = `/api/client/${DEFAULT_CONFIG.API_VERSION}`
|
|
14
|
+
export const HTTPS_SCHEMA = DEFAULT_CONFIG.HTTPS_SCHEMA
|
|
15
|
+
export const DB_NAME = database_name
|
|
16
|
+
export const AUTH_CONFIG = {
|
|
17
|
+
authCollection: auth_collection,
|
|
18
|
+
userCollection: collection_name,
|
|
19
|
+
resetPasswordCollection: "reset-password-requests",
|
|
20
|
+
resetPasswordConfig: configuration['local-userpass'].config,
|
|
21
|
+
user_id_field
|
|
22
|
+
}
|
package/src/fastify.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { FastifyRequest as FastifyRequestType } from 'fastify'
|
|
2
|
+
|
|
3
|
+
type User = Record<string, unknown>
|
|
4
|
+
type UserData = Record<string, unknown>
|
|
5
|
+
|
|
6
|
+
declare module 'fastify' {
|
|
7
|
+
interface FastifyInstance {
|
|
8
|
+
jwtAuthentication(req: FastifyRequestType, rep: FastifyReply): Promise<void>
|
|
9
|
+
createAccessToken(user: User): string
|
|
10
|
+
createRefreshToken(user: User): string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface FastifyRequest {
|
|
14
|
+
user:
|
|
15
|
+
| {
|
|
16
|
+
id: string
|
|
17
|
+
typ: 'refresh'
|
|
18
|
+
sub: string
|
|
19
|
+
user_data: UserData
|
|
20
|
+
user: User
|
|
21
|
+
}
|
|
22
|
+
| {
|
|
23
|
+
typ: 'access'
|
|
24
|
+
user_data: UserData
|
|
25
|
+
id: string
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { GenerateEndpointsParams } from './interface'
|
|
2
|
+
import { generateHandler, getMethodsConfig } from './utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* > Generates all HTTP endpoints
|
|
6
|
+
* @testable
|
|
7
|
+
* @param app -> the fastify instance
|
|
8
|
+
* @param functionsList -> the list of all functions
|
|
9
|
+
* @param endpointsList -> the list of all endpoints
|
|
10
|
+
*/
|
|
11
|
+
export const generateEndpoints = async ({
|
|
12
|
+
app,
|
|
13
|
+
functionsList,
|
|
14
|
+
endpointsList
|
|
15
|
+
}: GenerateEndpointsParams) => {
|
|
16
|
+
endpointsList.forEach(({ http_method, route, disabled, function_name }) => {
|
|
17
|
+
const currentFunction = functionsList[function_name]
|
|
18
|
+
|
|
19
|
+
if (disabled || !currentFunction) return
|
|
20
|
+
|
|
21
|
+
const handler = generateHandler({ app, currentFunction, functionsList })
|
|
22
|
+
const currentMethod = getMethodsConfig(app, handler, `/app/:appId/endpoint/${route}`)[
|
|
23
|
+
http_method
|
|
24
|
+
]
|
|
25
|
+
currentMethod()
|
|
26
|
+
})
|
|
27
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { FastifyInstance } from 'fastify'
|
|
2
|
+
import { Function, Functions } from '../functions/interface'
|
|
3
|
+
|
|
4
|
+
export type GenerateEndpointsParams = {
|
|
5
|
+
app: FastifyInstance
|
|
6
|
+
functionsList: Functions
|
|
7
|
+
endpointsList: Endpoints
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type GenerateHandlerParams = {
|
|
11
|
+
app: FastifyInstance
|
|
12
|
+
currentFunction: Function
|
|
13
|
+
functionsList: Functions
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type HTTP_METHOD<T> = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | T
|
|
17
|
+
|
|
18
|
+
export type Endpoint<T = 'ALL'> = {
|
|
19
|
+
http_method: HTTP_METHOD<T>
|
|
20
|
+
route: string
|
|
21
|
+
function_name: string
|
|
22
|
+
secret_name: string
|
|
23
|
+
validation_method: string
|
|
24
|
+
respond_result: boolean
|
|
25
|
+
fetch_custom_user_data: boolean
|
|
26
|
+
create_user_on_auth: boolean
|
|
27
|
+
disabled: boolean
|
|
28
|
+
}
|
|
29
|
+
export type Endpoints<T = 'ALL'> = Endpoint<T>[]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
|
|
3
|
+
|
|
4
|
+
import { services } from '../../services'
|
|
5
|
+
|
|
6
|
+
import { GenerateContext } from '../../utils/context'
|
|
7
|
+
import { Endpoints, GenerateHandlerParams } from './interface'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* > Loads the endpoint config json file
|
|
11
|
+
* @testable
|
|
12
|
+
*/
|
|
13
|
+
export const loadEndpoints = async (): Promise<Endpoints> => {
|
|
14
|
+
const config: Endpoints<'*'> = JSON.parse(
|
|
15
|
+
fs.readFileSync('http_endpoints/config.json', 'utf-8')
|
|
16
|
+
)
|
|
17
|
+
return config.map(({ http_method, ...endpoint }) => ({
|
|
18
|
+
http_method: http_method === '*' ? 'ALL' : http_method,
|
|
19
|
+
...endpoint
|
|
20
|
+
}))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* > Creates an object with a config for all HTTP methods
|
|
25
|
+
* @testable
|
|
26
|
+
* @param app -> the fastify instance
|
|
27
|
+
* @param handler -> the handler function for that route
|
|
28
|
+
* @param endpoint -> the current endpoint
|
|
29
|
+
*/
|
|
30
|
+
export const getMethodsConfig = (
|
|
31
|
+
app: FastifyInstance,
|
|
32
|
+
handler: ReturnType<typeof generateHandler>,
|
|
33
|
+
endpoint: string
|
|
34
|
+
) => ({
|
|
35
|
+
ALL: () => app.all(endpoint, handler),
|
|
36
|
+
GET: () => app.get(endpoint, handler),
|
|
37
|
+
POST: () => app.post(endpoint, handler),
|
|
38
|
+
PUT: () => app.put(endpoint, handler),
|
|
39
|
+
PATCH: () => app.patch(endpoint, handler),
|
|
40
|
+
DELETE: () => app.delete(endpoint, handler)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* > Creates an handler function for a single endpoint
|
|
45
|
+
* @testable
|
|
46
|
+
* @param app -> the fastify instance
|
|
47
|
+
* @param currentFunction -> the name of the function that should be called for that endpoint
|
|
48
|
+
* @param functionsList -> the list of all functions
|
|
49
|
+
*/
|
|
50
|
+
export const generateHandler = ({
|
|
51
|
+
app,
|
|
52
|
+
currentFunction,
|
|
53
|
+
functionsList
|
|
54
|
+
}: GenerateHandlerParams) => {
|
|
55
|
+
return async (req: FastifyRequest, res: FastifyReply) => {
|
|
56
|
+
try {
|
|
57
|
+
const response = await GenerateContext({
|
|
58
|
+
args: [req],
|
|
59
|
+
app,
|
|
60
|
+
rules: {}, //TODO -> check rules
|
|
61
|
+
user: req.user,
|
|
62
|
+
currentFunction,
|
|
63
|
+
functionsList,
|
|
64
|
+
services
|
|
65
|
+
})
|
|
66
|
+
res.send(response)
|
|
67
|
+
} catch (e) {
|
|
68
|
+
console.log(e)
|
|
69
|
+
}
|
|
70
|
+
return {}
|
|
71
|
+
}
|
|
72
|
+
}
|