@volcanicminds/backend 0.2.27 → 0.2.29

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 (59) hide show
  1. package/README.md +26 -18
  2. package/TODO.md +0 -1
  3. package/dist/index.js +46 -20
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/api/auth/controller/auth.js +136 -17
  6. package/dist/lib/api/auth/controller/auth.js.map +1 -1
  7. package/dist/lib/api/auth/routes.js +107 -13
  8. package/dist/lib/api/auth/routes.js.map +1 -1
  9. package/dist/lib/api/health/routes.js +2 -2
  10. package/dist/lib/api/health/routes.js.map +1 -1
  11. package/dist/lib/api/users/routes.js +12 -14
  12. package/dist/lib/api/users/routes.js.map +1 -1
  13. package/dist/lib/config/plugins.js +24 -0
  14. package/dist/lib/config/plugins.js.map +1 -0
  15. package/dist/lib/hooks/onRequest.js +13 -9
  16. package/dist/lib/hooks/onRequest.js.map +1 -1
  17. package/dist/lib/loader/plugins.js +23 -0
  18. package/dist/lib/loader/plugins.js.map +1 -0
  19. package/dist/lib/loader/router.js +66 -35
  20. package/dist/lib/loader/router.js.map +1 -1
  21. package/dist/lib/loader/schemas.js +8 -3
  22. package/dist/lib/loader/schemas.js.map +1 -1
  23. package/dist/lib/middleware/isAdmin.js +5 -4
  24. package/dist/lib/middleware/isAdmin.js.map +1 -1
  25. package/dist/lib/middleware/isAuthenticated.js +7 -6
  26. package/dist/lib/middleware/isAuthenticated.js.map +1 -1
  27. package/dist/lib/middleware/postAuth.js +19 -0
  28. package/dist/lib/middleware/postAuth.js.map +1 -0
  29. package/dist/lib/middleware/preAuth.js +17 -0
  30. package/dist/lib/middleware/preAuth.js.map +1 -0
  31. package/dist/lib/util/generate.js +10 -0
  32. package/dist/lib/util/generate.js.map +1 -0
  33. package/dist/lib/util/regexp.js +13 -13
  34. package/dist/lib/util/regexp.js.map +1 -1
  35. package/index.d.ts +2 -1
  36. package/index.ts +57 -33
  37. package/lib/api/auth/controller/auth.ts +118 -23
  38. package/lib/api/auth/routes.ts +107 -14
  39. package/lib/api/health/routes.ts +2 -2
  40. package/lib/api/users/routes.ts +12 -14
  41. package/lib/config/plugins.ts +24 -0
  42. package/lib/hooks/onRequest.ts +13 -19
  43. package/lib/loader/plugins.ts +22 -0
  44. package/lib/loader/router.ts +71 -34
  45. package/lib/loader/schemas.ts +7 -3
  46. package/lib/middleware/isAdmin.ts +3 -3
  47. package/lib/middleware/isAuthenticated.ts +5 -5
  48. package/lib/middleware/postAuth.ts +5 -0
  49. package/lib/middleware/preAuth.ts +3 -0
  50. package/lib/util/generate.ts +6 -0
  51. package/lib/util/regexp.ts +34 -32
  52. package/package.json +1 -1
  53. package/types/global.d.ts +15 -1
  54. package/dist/lib/api/auth/controller/password.js +0 -23
  55. package/dist/lib/api/auth/controller/password.js.map +0 -1
  56. package/dist/lib/middleware/example.js +0 -13
  57. package/dist/lib/middleware/example.js.map +0 -1
  58. package/lib/api/auth/controller/password.ts +0 -21
  59. package/lib/middleware/example.ts +0 -12
package/index.ts CHANGED
@@ -6,6 +6,7 @@ dotenv.config()
6
6
  import yn from './lib/util/yn'
7
7
  import logger from './lib/util/logger'
8
8
  import * as mark from './lib/util/mark'
9
+ import * as loaderPlugins from './lib/loader/plugins'
9
10
  import * as loaderRoles from './lib/loader/roles'
10
11
  import * as loaderRouter from './lib/loader/router'
11
12
  import * as loaderHooks from './lib/loader/hooks'
@@ -26,6 +27,7 @@ import fastifyApollo, { fastifyApolloDrainPlugin } from '@as-integrations/fastif
26
27
  import { myContextFunction, MyContext } from './lib/apollo/context'
27
28
  import resolvers from './lib/apollo/resolvers'
28
29
  import typeDefs from './lib/apollo/type-defs'
30
+ import { UserManagement } from './types/global'
29
31
 
30
32
  global.log = logger
31
33
 
@@ -131,7 +133,7 @@ async function addFastifySwagger(fastify: FastifyInstance) {
131
133
  }
132
134
  }
133
135
 
134
- const start = async () => {
136
+ const start = async (decorators) => {
135
137
  const begin = new Date().getTime()
136
138
  mark.print(logger)
137
139
  global.roles = loaderRoles.load()
@@ -140,41 +142,16 @@ const start = async () => {
140
142
  const fastify = await Fastify(opts)
141
143
 
142
144
  const { HOST: host = '0.0.0.0', PORT: port = '2230', GRAPHQL } = process.env
143
- const { SRV_CORS, SRV_HELMET, SRV_RATELIMIT, SRV_COMPRESS, JWT_SECRET, JWT_EXPIRES_IN = '15d' } = process.env
145
+ const { JWT_SECRET, JWT_EXPIRES_IN = '15d' } = process.env
144
146
 
145
147
  const loadApollo = yn(GRAPHQL, false)
146
- const addPluginCors = yn(SRV_CORS, false)
147
- const addPluginHelmet = yn(SRV_HELMET, false)
148
- const addPluginRateLimit = yn(SRV_RATELIMIT, false)
149
- const addPluginCompress = yn(SRV_COMPRESS, false)
150
-
151
- log.t && log.trace(`Attach Apollo Server ${loadApollo}`)
152
- log.t && log.trace(`Add plugin CORS: ${addPluginCors}`)
153
- log.t && log.trace(`Add plugin HELMET: ${!loadApollo ? addPluginHelmet : 'Not usable with Apollo'}`)
154
- log.t && log.trace(`Add plugin COMPRESS: ${addPluginCompress}`)
155
- log.t && log.trace(`Add plugin RATELIMIT: ${addPluginRateLimit}`)
148
+ const plugins = loaderPlugins.load()
156
149
 
157
150
  // Helmet is not usable with Apollo Server
158
- !loadApollo && addPluginHelmet && (await fastify.register(helmet))
159
- addPluginRateLimit && (await fastify.register(rateLimit))
160
- addPluginCors &&
161
- (await fastify.register(cors, {
162
- origin: '*',
163
- methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'],
164
- maxAge: 31536000,
165
- credentials: true,
166
- allowedHeaders: [
167
- 'Content-Type',
168
- 'Content-Length',
169
- 'Authorization',
170
- 'Origin',
171
- 'v-total',
172
- 'v-count',
173
- 'v-page',
174
- 'v-pageSize'
175
- ]
176
- }))
177
- addPluginCompress && (await fastify.register(compress))
151
+ !loadApollo && plugins?.helmet && (await fastify.register(helmet))
152
+ plugins?.rateLimit && (await fastify.register(rateLimit))
153
+ plugins?.cors && (await fastify.register(cors, plugins.cors || {}))
154
+ plugins?.compress && (await fastify.register(compress))
178
155
 
179
156
  // JWT Validator
180
157
  log.t && log.trace(`Add JWT - expiresIn: ${JWT_EXPIRES_IN}`)
@@ -188,6 +165,52 @@ const start = async () => {
188
165
  await addApolloRouting(fastify, apollo)
189
166
  await addFastifyRouting(fastify)
190
167
 
168
+ // defaults
169
+ decorators = {
170
+ userManager: {
171
+ createUser(data: any) {
172
+ throw Error('Not implemented')
173
+ },
174
+ resetExternalId(data: any) {
175
+ throw Error('Not implemented')
176
+ },
177
+ updateUserById(id: string, user: any) {
178
+ throw Error('Not implemented')
179
+ },
180
+ retrieveUserById(id: string) {
181
+ throw Error('Not implemented')
182
+ },
183
+ retrieveUserByEmail(email: string) {
184
+ throw Error('Not implemented')
185
+ },
186
+ retrieveUserByExternalId(externalId: string) {
187
+ throw Error('Not implemented')
188
+ },
189
+ retrieveUserByPassword(email: string, password: string) {
190
+ throw Error('Not implemented')
191
+ },
192
+ changePassword(email: string, password: string, oldPassword: string) {
193
+ throw Error('Not implemented')
194
+ },
195
+ enableUserById(id: string) {
196
+ throw Error('Not implemented')
197
+ },
198
+ disableUserById(id: string) {
199
+ throw Error('Not implemented')
200
+ },
201
+ isValidUser(data: any) {
202
+ throw Error('Not implemented')
203
+ }
204
+ } as UserManagement,
205
+ ...decorators
206
+ }
207
+
208
+ await Promise.all(
209
+ Object.keys(decorators || {}).map(async (key) => {
210
+ await fastify.decorate(key, decorators[key])
211
+ })
212
+ )
213
+
191
214
  await fastify
192
215
  .listen({
193
216
  port: Number(port),
@@ -216,7 +239,8 @@ export {
216
239
  Roles,
217
240
  Route,
218
241
  RouteConfig,
219
- ConfiguredRoute
242
+ ConfiguredRoute,
243
+ UserManagement
220
244
  } from './types/global'
221
245
 
222
246
  /**
@@ -1,31 +1,126 @@
1
1
  import { FastifyReply, FastifyRequest } from 'fastify'
2
- import { AuthenticatedUser } from '../../../../types/global'
2
+ import * as regExp from '../../../util/regexp'
3
+
4
+ export async function register(req: FastifyRequest, reply: FastifyReply) {
5
+ const { password1: password, password2, ...data } = req.data()
6
+
7
+ if (!data.username) {
8
+ return reply.status(404).send(Error('Username not valid'))
9
+ }
10
+ if (!data.email || !regExp.email.test(data.email)) {
11
+ return reply.status(404).send(Error('Email not valid'))
12
+ }
13
+ if (!password || !regExp.password.test(password)) {
14
+ return reply.status(404).send(Error('Password not valid'))
15
+ }
16
+ if (!password2 || password2 !== password) {
17
+ return reply.status(404).send(Error('Repeated password not match'))
18
+ }
19
+
20
+ // public is the default
21
+ const publicRole = global.roles?.public?.code || 'public'
22
+ data.roles = (data.requiredRoles || []).map((r) => global.roles[r]?.code).filter((r) => !!r)
23
+ if (!data.roles.includes(publicRole)) {
24
+ data.roles.push(publicRole)
25
+ }
26
+
27
+ const user = await req.server['userManager'].createUser({ ...data, password: password })
28
+ if (!user) {
29
+ return reply.status(400).send(Error('User not registered'))
30
+ }
31
+
32
+ return user
33
+ }
34
+
35
+ export async function unregister(req: FastifyRequest, reply: FastifyReply) {
36
+ const { email, password } = req.data()
37
+
38
+ let user = await req.server['userManager'].retrieveUserByPassword(email, password)
39
+ let isValid = await req.server['userManager'].isValidUser(user)
40
+
41
+ if (!isValid) {
42
+ return reply.status(403).send(Error('Wrong credentials'))
43
+ }
44
+
45
+ if (!user.enabled) {
46
+ return reply.status(403).send(Error('User not enabled'))
47
+ }
48
+
49
+ user = await req.server['userManager'].disableUserById(user?.id)
50
+ isValid = await req.server['userManager'].isValidUser(user)
51
+
52
+ if (!isValid) {
53
+ return reply.status(400).send(Error('User not valid'))
54
+ }
55
+
56
+ return { ok: true }
57
+ }
58
+
59
+ export async function changePassword(req: FastifyRequest, reply: FastifyReply) {
60
+ const { email, oldPassword, newPassword1, newPassword2 } = req.data()
61
+
62
+ if (!newPassword1 || !regExp.password.test(newPassword1)) {
63
+ return reply.status(404).send(Error('New password not valid'))
64
+ }
65
+
66
+ if (!newPassword2 || newPassword2 !== newPassword1) {
67
+ return reply.status(404).send(Error('Repeated new password not match'))
68
+ }
69
+
70
+ let user = await req.server['userManager'].retrieveUserByPassword(email, oldPassword)
71
+ let isValid = await req.server['userManager'].isValidUser(user)
72
+
73
+ if (!isValid) {
74
+ return reply.status(403).send(Error('Wrong credentials'))
75
+ }
76
+
77
+ if (!user.enabled) {
78
+ return reply.status(403).send(Error('User not enabled'))
79
+ }
80
+
81
+ user = await req.server['userManager'].changePassword(email, newPassword1, oldPassword)
82
+ isValid = await req.server['userManager'].isValidUser(user)
83
+ return { ok: isValid }
84
+ }
3
85
 
4
86
  export async function login(req: FastifyRequest, reply: FastifyReply) {
5
- const { email = '', password = '' } = req.data()
6
-
7
- // TODO: use UserManagement.find and check password
8
- // demo code here
9
- const username = email.substr(0, email.indexOf('@')) || 'jerry'
10
- const roleList = [username === 'admin' ? roles.admin : username === 'vminds' ? roles.backoffice : roles.public]
11
- const user =
12
- username !== null
13
- ? ({
14
- id: 306, // user id
15
- name: username, // optional
16
- email: email,
17
- roles: roleList
18
- } as AuthenticatedUser)
19
- : null
20
-
21
- // TODO: review if email is important to include in token (for a security purpose)
87
+ const { email, password } = req.data()
88
+
89
+ if (!email || !regExp.email.test(email)) {
90
+ return reply.status(404).send(Error('Email not valid'))
91
+ }
92
+ if (!password || !regExp.password.test(password)) {
93
+ return reply.status(404).send(Error('Password not valid'))
94
+ }
95
+
96
+ const user = await req.server['userManager'].retrieveUserByPassword(email, password)
97
+ const isValid = await req.server['userManager'].isValidUser(user)
98
+
99
+ if (!isValid) {
100
+ return reply.status(403).send(Error('Wrong credentials'))
101
+ }
102
+
103
+ if (!user.enabled) {
104
+ return reply.status(403).send(Error('User not enabled'))
105
+ }
106
+
107
+ // log.trace('User: ' + JSON.stringify(user) + ' ' + roles)
22
108
  // https://www.iana.org/assignments/jwt/jwt.xhtml
23
- const token = user !== null ? await reply.jwtSign({ sub: user.id, name: user.name, email: user.email }) : null
24
- reply.send({ ...user, token: token || null, roles: roleList.map((r) => r.code) })
109
+ const token = user !== null ? await reply.jwtSign({ sub: user.externalId }) : null
110
+ return {
111
+ ...user,
112
+ token: token || null,
113
+ roles: (user.roles || [global.role?.public?.code || 'public']).map((r) => r?.code || r)
114
+ }
25
115
  }
26
116
 
27
- export async function demo(req: FastifyRequest, reply: FastifyReply) {
28
- // JSON.stringify(req.user)
117
+ export async function invalidateTokens(req: FastifyRequest, reply: FastifyReply) {
118
+ let isValid = await req.server['userManager'].isValidUser(req.user)
119
+ if (!isValid) {
120
+ return reply.status(403).send(Error('User not linked'))
121
+ }
29
122
 
30
- reply.send({ ok: req.user })
123
+ const user = await req.server['userManager'].resetExternalId(req.user?.id)
124
+ isValid = await req.server['userManager'].isValidUser(user)
125
+ return { ok: isValid }
31
126
  }
@@ -1,20 +1,111 @@
1
1
  module.exports = {
2
2
  config: {
3
- title: 'User useful functions',
4
- description: 'User useful functions',
3
+ title: 'Authentication functions',
4
+ description: 'Authentication functions',
5
5
  controller: 'controller',
6
6
  tags: ['auth'],
7
-
8
7
  deprecated: false,
9
- version: false
8
+ version: false,
9
+ enable: true
10
10
  },
11
11
  routes: [
12
+ {
13
+ method: 'POST',
14
+ path: '/register',
15
+ roles: [],
16
+ handler: 'auth.register',
17
+ middlewares: ['global.preAuth', 'global.postAuth'],
18
+ config: {
19
+ title: 'Register new user',
20
+ description: 'Register a new user',
21
+ body: {
22
+ type: 'object',
23
+ properties: {
24
+ username: { type: 'string' },
25
+ email: { type: 'string' },
26
+ password1: { type: 'string' },
27
+ password2: { type: 'string' },
28
+ requiredRoles: { type: 'array', items: { type: 'string' } }
29
+ }
30
+ },
31
+ response: {
32
+ 200: {
33
+ description: 'Default response',
34
+ type: 'object',
35
+ properties: {
36
+ id: { type: 'string' },
37
+ externalId: { type: 'string' },
38
+ username: { type: 'string' },
39
+ email: { type: 'string' },
40
+ enabled: { type: 'boolean' },
41
+ roles: { type: 'array', items: { type: 'string' } }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ },
47
+ {
48
+ method: 'POST',
49
+ path: '/unregister',
50
+ roles: [],
51
+ handler: 'auth.unregister',
52
+ middlewares: ['global.preAuth', 'global.postAuth'],
53
+ config: {
54
+ title: 'Unregister existing user',
55
+ description: 'Unregister an existing user',
56
+ body: {
57
+ type: 'object',
58
+ properties: {
59
+ email: { type: 'string' },
60
+ password: { type: 'string' }
61
+ }
62
+ },
63
+ response: {
64
+ 200: {
65
+ description: 'Default response',
66
+ type: 'object',
67
+ properties: {
68
+ ok: { type: 'boolean' }
69
+ }
70
+ }
71
+ }
72
+ }
73
+ },
74
+ {
75
+ method: 'POST',
76
+ path: '/change-password',
77
+ roles: [],
78
+ handler: 'auth.changePassword',
79
+ middlewares: [],
80
+ config: {
81
+ title: 'Change password',
82
+ description: 'Change password for an existing user',
83
+ body: {
84
+ type: 'object',
85
+ properties: {
86
+ email: { type: 'string' },
87
+ oldPassword: { type: 'string' },
88
+ newPassword1: { type: 'string' },
89
+ newPassword2: { type: 'string' }
90
+ }
91
+ },
92
+ response: {
93
+ 200: {
94
+ description: 'Default response',
95
+ type: 'object',
96
+ properties: {
97
+ ok: { type: 'boolean' }
98
+ }
99
+ }
100
+ }
101
+ }
102
+ },
12
103
  {
13
104
  method: 'POST',
14
105
  path: '/login',
15
106
  roles: [],
16
107
  handler: 'auth.login',
17
- middlewares: [],
108
+ middlewares: ['global.preAuth', 'global.postAuth'],
18
109
  config: {
19
110
  title: 'Login',
20
111
  description: 'Basic login authentication',
@@ -30,24 +121,26 @@ module.exports = {
30
121
  description: 'Default response',
31
122
  type: 'object',
32
123
  properties: {
33
- id: { type: 'number' },
34
- name: { type: 'string' },
35
- token: { type: 'string' },
36
- roles: { type: 'array', items: { type: 'string' } }
124
+ id: { type: 'string' },
125
+ externalId: { type: 'string' },
126
+ username: { type: 'string' },
127
+ email: { type: 'string' },
128
+ roles: { type: 'array', items: { type: 'string' } },
129
+ token: { type: 'string' }
37
130
  }
38
131
  }
39
132
  }
40
133
  }
41
134
  },
42
135
  {
43
- method: 'GET',
44
- path: '/demo',
136
+ method: 'POST',
137
+ path: '/invalidate-tokens',
45
138
  roles: [],
46
- handler: 'auth.demo',
139
+ handler: 'auth.invalidateTokens',
47
140
  middlewares: ['global.isAuthenticated'],
48
141
  config: {
49
- title: 'For debug purpose',
50
- description: 'Demo login authentication',
142
+ title: 'Invalidate all tokens',
143
+ description: 'Invalidate all tokens',
51
144
  response: {
52
145
  200: {
53
146
  description: 'Default response',
@@ -1,7 +1,7 @@
1
1
  module.exports = {
2
2
  config: {
3
- title: 'Health useful functions',
4
- description: 'Health useful functions',
3
+ title: 'Health functions',
4
+ description: 'Health functions',
5
5
  controller: 'controller',
6
6
  tags: ['health']
7
7
  },
@@ -1,7 +1,7 @@
1
1
  module.exports = {
2
2
  config: {
3
- title: 'User useful functions',
4
- description: 'User useful functions',
3
+ title: 'User functions',
4
+ description: 'User functions',
5
5
  controller: 'controller',
6
6
  tags: ['users'],
7
7
  version: false
@@ -10,25 +10,27 @@ module.exports = {
10
10
  {
11
11
  method: 'GET',
12
12
  path: '/',
13
- roles: [],
13
+ roles: [roles.public],
14
14
  handler: 'user.user',
15
15
  middlewares: ['global.isAuthenticated'],
16
16
  config: {
17
17
  title: 'Get current user',
18
18
  description: 'Get current user',
19
19
  response: {
20
- 403: {
21
- description: 'Unauthorized',
22
- type: 'string'
23
- },
24
20
  200: {
25
21
  description: 'Default response',
26
22
  type: 'object',
27
23
  properties: {
28
- id: { type: 'number' },
29
- name: { type: 'string' },
24
+ id: { type: 'string' },
25
+ externalId: { type: 'string' },
26
+ username: { type: 'string' },
30
27
  email: { type: 'string' },
31
- roles: { type: 'array', items: { type: 'string' } }
28
+ enabled: { type: 'boolean' },
29
+ enabledAt: { type: 'string' },
30
+ roles: { type: 'array', items: { type: 'string' } },
31
+ createdAt: { type: 'string' },
32
+ version: { type: 'number' },
33
+ updatedAt: { type: 'string' }
32
34
  }
33
35
  }
34
36
  }
@@ -44,10 +46,6 @@ module.exports = {
44
46
  title: 'Check if is an admin',
45
47
  description: 'Check if the current user is an admin',
46
48
  response: {
47
- 403: {
48
- description: 'Unauthorized',
49
- type: 'string'
50
- },
51
49
  200: {
52
50
  description: 'Default response',
53
51
  type: 'object',
@@ -0,0 +1,24 @@
1
+ 'use strict'
2
+
3
+ module.exports = [
4
+ {
5
+ name: 'cors',
6
+ enable: false,
7
+ options: {}
8
+ },
9
+ {
10
+ name: 'rateLimit',
11
+ enable: false,
12
+ options: {}
13
+ },
14
+ {
15
+ name: 'helmet',
16
+ enable: false,
17
+ options: {}
18
+ },
19
+ {
20
+ name: 'compress',
21
+ enable: false,
22
+ options: {}
23
+ }
24
+ ]
@@ -6,8 +6,8 @@ module.exports = async (req, reply) => {
6
6
  log.i && (req.startedAt = new Date())
7
7
  req.data = () => getData(req)
8
8
  req.parameters = () => getParams(req)
9
- req.roles = () => ((req.user && req.user.roles) || []).map((role: Role) => role?.code) || []
10
- req.hasRole = (r: Role) => ((req.user && req.user.roles) || []).some((role: Role) => role?.code === r?.code)
9
+ req.roles = () => (req.user ? req.user.roles : [roles.public])
10
+ req.hasRole = (r: Role) => (req.user ? req.user.roles : [roles.public]).some((role) => role === r?.code)
11
11
 
12
12
  // authorization check
13
13
  const auth = req.headers?.authorization || ''
@@ -15,23 +15,17 @@ module.exports = async (req, reply) => {
15
15
  const isRoutePublic = (req.routeConfig.requiredRoles || []).some((role: Role) => role.code === roles.public.code)
16
16
 
17
17
  if (prefix === 'Bearer' && token != null) {
18
- const user: AuthenticatedUser = {} as AuthenticatedUser
18
+ let user: AuthenticatedUser = {} as AuthenticatedUser
19
19
  try {
20
20
  const tokenData = reply.server.jwt.verify(token)
21
- user.id = tokenData.sub
22
- user.name = tokenData.name
23
- user.email = tokenData.email
24
- user.roles = [roles.public, roles.admin]
25
-
26
- // if (global.npmDebugServerStarted) {
27
- // user.id = user.id || 123
28
- // user.name = user.name || 'Jerry Seinfeld'
29
- // user.email = user.email || 'jerry@george.com'
30
- // user.roles = [roles.public, roles.backoffice]
31
- // log.debug('Inject demo user ' + user.id)
32
- // }
33
-
34
- //TODO: recall plugin UserManagement for find user or error
21
+ user = await req.server['userManager'].retrieveUserByExternalId(tokenData?.sub)
22
+ if (!user) {
23
+ return reply.status(404).send({ statusCode: 404, code: 'USER_NOT_FOUND', message: 'User not found' })
24
+ }
25
+ const isValid = await req.server['userManager'].isValidUser(user)
26
+ if (!isValid) {
27
+ return reply.status(404).send({ statusCode: 404, code: 'USER_NOT_VALID', message: 'User not valid' })
28
+ }
35
29
 
36
30
  // ok, we have the full user here
37
31
  req.user = user
@@ -43,13 +37,13 @@ module.exports = async (req, reply) => {
43
37
 
44
38
  if (req.routeConfig.requiredRoles?.length > 0) {
45
39
  const { method = '', url = '', requiredRoles } = req.routeConfig
46
- const userRoles: string[] = req.user?.roles?.map(({ code }) => code) || []
40
+ const userRoles: string[] = req.user?.roles?.map((code) => code) || []
47
41
  const resolvedRoles = userRoles.length > 0 ? requiredRoles.filter((r) => userRoles.includes(r.code)) : []
48
42
 
49
43
  if (!resolvedRoles.length) {
50
44
  log.w && log.warn(`Not allowed to call ${method.toUpperCase()} ${url}`)
51
45
  return reply
52
- .code(403)
46
+ .status(403)
53
47
  .send({ statusCode: 403, code: 'ROLE_NOT_ALLOWED', message: 'Not allowed to call this route' })
54
48
  }
55
49
  }
@@ -0,0 +1,22 @@
1
+ import { config } from 'dotenv'
2
+
3
+ const glob = require('glob')
4
+
5
+ export function load() {
6
+ const plugins: any = {}
7
+
8
+ const patterns = [`${__dirname}/../config/plugins.{ts,js}`, `${process.cwd()}/src/config/plugins.{ts,js}`]
9
+ patterns.forEach((pattern) => {
10
+ log.t && log.trace('Looking for ' + pattern)
11
+ glob.sync(pattern).forEach((f: string) => {
12
+ const configPlugins = require(f)
13
+ configPlugins.forEach((plugin) => {
14
+ plugins[plugin.name] = plugin.enable ? plugin.options : false
15
+ log.t && log.trace(`* Plugin ${plugin.name} ${plugin.enable ? 'enabled' : 'disabled'}`)
16
+ })
17
+ })
18
+ })
19
+ const enabledPulgins = Object.keys(plugins).filter((p) => !!plugins[p])
20
+ log.d && log.debug(`Plugins loaded: ${enabledPulgins.length > 0 ? enabledPulgins.join(', ') : 0}`)
21
+ return plugins
22
+ }