@volcanicminds/backend 0.2.28 → 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 (55) hide show
  1. package/README.md +0 -7
  2. package/dist/index.js +39 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/lib/api/auth/controller/auth.js +136 -17
  5. package/dist/lib/api/auth/controller/auth.js.map +1 -1
  6. package/dist/lib/api/auth/routes.js +107 -13
  7. package/dist/lib/api/auth/routes.js.map +1 -1
  8. package/dist/lib/api/health/routes.js +2 -2
  9. package/dist/lib/api/health/routes.js.map +1 -1
  10. package/dist/lib/api/users/routes.js +12 -14
  11. package/dist/lib/api/users/routes.js.map +1 -1
  12. package/dist/lib/hooks/onRequest.js +13 -9
  13. package/dist/lib/hooks/onRequest.js.map +1 -1
  14. package/dist/lib/loader/plugins.js +0 -1
  15. package/dist/lib/loader/plugins.js.map +1 -1
  16. package/dist/lib/loader/router.js +66 -35
  17. package/dist/lib/loader/router.js.map +1 -1
  18. package/dist/lib/loader/schemas.js +8 -3
  19. package/dist/lib/loader/schemas.js.map +1 -1
  20. package/dist/lib/middleware/isAdmin.js +5 -4
  21. package/dist/lib/middleware/isAdmin.js.map +1 -1
  22. package/dist/lib/middleware/isAuthenticated.js +7 -6
  23. package/dist/lib/middleware/isAuthenticated.js.map +1 -1
  24. package/dist/lib/middleware/postAuth.js +19 -0
  25. package/dist/lib/middleware/postAuth.js.map +1 -0
  26. package/dist/lib/middleware/preAuth.js +17 -0
  27. package/dist/lib/middleware/preAuth.js.map +1 -0
  28. package/dist/lib/util/generate.js +10 -0
  29. package/dist/lib/util/generate.js.map +1 -0
  30. package/dist/lib/util/regexp.js +13 -13
  31. package/dist/lib/util/regexp.js.map +1 -1
  32. package/index.d.ts +2 -1
  33. package/index.ts +50 -2
  34. package/lib/api/auth/controller/auth.ts +118 -23
  35. package/lib/api/auth/routes.ts +107 -14
  36. package/lib/api/health/routes.ts +2 -2
  37. package/lib/api/users/routes.ts +12 -14
  38. package/lib/hooks/onRequest.ts +13 -19
  39. package/lib/loader/plugins.ts +0 -1
  40. package/lib/loader/router.ts +71 -34
  41. package/lib/loader/schemas.ts +7 -3
  42. package/lib/middleware/isAdmin.ts +3 -3
  43. package/lib/middleware/isAuthenticated.ts +5 -5
  44. package/lib/middleware/postAuth.ts +5 -0
  45. package/lib/middleware/preAuth.ts +3 -0
  46. package/lib/util/generate.ts +6 -0
  47. package/lib/util/regexp.ts +34 -32
  48. package/package.json +1 -1
  49. package/types/global.d.ts +15 -1
  50. package/dist/lib/api/auth/controller/password.js +0 -23
  51. package/dist/lib/api/auth/controller/password.js.map +0 -1
  52. package/dist/lib/middleware/example.js +0 -13
  53. package/dist/lib/middleware/example.js.map +0 -1
  54. package/lib/api/auth/controller/password.ts +0 -21
  55. package/lib/middleware/example.ts +0 -12
@@ -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',
@@ -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
  }
@@ -13,7 +13,6 @@ export function load() {
13
13
  configPlugins.forEach((plugin) => {
14
14
  plugins[plugin.name] = plugin.enable ? plugin.options : false
15
15
  log.t && log.trace(`* Plugin ${plugin.name} ${plugin.enable ? 'enabled' : 'disabled'}`)
16
- log.error(plugin)
17
16
  })
18
17
  })
19
18
  })
@@ -1,3 +1,4 @@
1
+ import yn from '../util/yn'
1
2
  import { Route, ConfiguredRoute, RouteConfig } from '../../types/global'
2
3
  import { FastifyReply, FastifyRequest } from 'fastify'
3
4
 
@@ -8,6 +9,7 @@ const methods = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'PATCH', 'OPTIONS']
8
9
  export function load(): ConfiguredRoute[] {
9
10
  const validRoutes: ConfiguredRoute[] = []
10
11
  const patterns = [`${__dirname}/../api/**/routes.{ts,js}`, `${process.cwd()}/src/api/**/routes.{ts,js}`]
12
+ const authMiddlewares = ['global.isAuthenticated', 'global.isAdmin']
11
13
 
12
14
  patterns.forEach((pattern) => {
13
15
  log.t && log.trace('Looking for ' + pattern)
@@ -20,11 +22,6 @@ export function load(): ConfiguredRoute[] {
20
22
  const routesjs = require(f)
21
23
  const { routes = [], config: defaultConfig = {} } = routesjs || {}
22
24
 
23
- // adjust default config
24
- if (!defaultConfig.enable) defaultConfig.enable = true
25
- if (defaultConfig.deprecated == null) defaultConfig.deprecated = false
26
- if (defaultConfig.controller == null) defaultConfig.controller = 'controller'
27
-
28
25
  log.t && log.trace(`* Add ${routes.length} routes from ${file}`)
29
26
 
30
27
  routes.forEach((route: Route, index: number) => {
@@ -35,14 +32,15 @@ export function load(): ConfiguredRoute[] {
35
32
  handler,
36
33
  config = {} as RouteConfig,
37
34
  middlewares = [],
38
- roles: requiredRole = []
35
+ roles: rs = []
39
36
  } = route
40
37
 
41
- if (
42
- !config?.security &&
43
- (requiredRole.some((r) => r.code !== roles.public.code) ||
44
- middlewares.some((m) => m === 'global.isAuthenticated'))
45
- ) {
38
+ const requiredRoles = !rs.length ? [roles.public] : rs
39
+ const reqAuth: boolean =
40
+ middlewares.some((m) => authMiddlewares.includes(m)) ||
41
+ requiredRoles.every((r) => r.code !== roles.public.code)
42
+
43
+ if (!config?.security && reqAuth) {
46
44
  config.security = 'bearer'
47
45
  }
48
46
 
@@ -50,11 +48,11 @@ export function load(): ConfiguredRoute[] {
50
48
  const {
51
49
  title = '',
52
50
  description = '',
53
- enable = defaultConfig.enable || true,
54
- deprecated = defaultConfig.deprecated || false,
55
- tags = defaultConfig.tags || false,
51
+ enable = yn(defaultConfig.enable, true),
52
+ deprecated = yn(defaultConfig.deprecated, false),
53
+ tags = defaultConfig.tags,
56
54
  version = defaultConfig.version || '',
57
- security = defaultConfig.security || undefined,
55
+ security = defaultConfig.security,
58
56
  query,
59
57
  params,
60
58
  body,
@@ -90,25 +88,26 @@ export function load(): ConfiguredRoute[] {
90
88
  }
91
89
  }
92
90
 
93
- if (errors.length == 0) {
94
- enable
95
- ? log.t &&
96
- log.trace(
97
- `* Method [${method}] path ${endpoint} handler ${handler} enabled with ${
98
- middlewares?.length || 0
99
- } middlewares`
100
- )
101
- : log.w && log.warn(`* Method [${method}] path ${endpoint} handler ${handler} disabled. Skip.`)
102
-
91
+ const toAdd = enable && errors.length === 0
92
+ toAdd
93
+ ? log.t &&
94
+ log.trace(
95
+ `* Method [${method}] path ${endpoint} handler ${handler} enabled with ${
96
+ middlewares?.length || 0
97
+ } middlewares`
98
+ )
99
+ : log.w && log.warn(`* Method [${method}] path ${endpoint} handler ${handler} disabled. Skip.`)
100
+
101
+ toAdd &&
103
102
  validRoutes.push({
104
103
  handler,
105
104
  method,
106
105
  path: '/' + endpoint,
107
106
  middlewares,
108
- roles: requiredRole,
107
+ roles: requiredRoles,
109
108
  enable,
110
109
  base,
111
- file: path.join(base, defaultConfig.controller, handlerParts[0]),
110
+ file: path.join(base, defaultConfig.controller || 'controller', handlerParts[0]),
112
111
  func: handlerParts[1],
113
112
  // swagger: doc
114
113
  doc: {
@@ -124,7 +123,6 @@ export function load(): ConfiguredRoute[] {
124
123
  response
125
124
  }
126
125
  })
127
- }
128
126
  })
129
127
  })
130
128
  })
@@ -133,26 +131,65 @@ export function load(): ConfiguredRoute[] {
133
131
  return validRoutes
134
132
  }
135
133
 
136
- function normalizeMiddlewarePath(base: string, middleware: string = '') {
134
+ async function tryToLoadFile(fileName: string) {
135
+ return new Promise((resolve, reject) => {
136
+ try {
137
+ const required = fileName ? require(fileName) : null
138
+ resolve(required)
139
+ } catch (err) {
140
+ reject(err)
141
+ }
142
+ })
143
+ }
144
+
145
+ async function loadMiddleware(base: string, middleware: string = '') {
137
146
  const key = 'global.'
138
- const idx = middleware.indexOf(key)
139
- return idx == 0
140
- ? path.resolve(__dirname + '/../middleware/' + middleware.substring(key.length))
141
- : path.resolve(base + '/middleware/' + middleware)
147
+ const isGlobal = middleware.indexOf(key) > -1
148
+ let required: any = null
149
+
150
+ if (isGlobal) {
151
+ const name = middleware.substring(key.length)
152
+ required = await tryToLoadFile(path.resolve(process.cwd() + '/src/middleware/' + name)).catch(async () => {
153
+ return await tryToLoadFile(path.resolve(__dirname + '/../middleware/' + name))
154
+ })
155
+ } else {
156
+ required = await tryToLoadFile(path.resolve(base + '/middleware/' + middleware))
157
+ }
158
+
159
+ if (!required) {
160
+ log.error(`Middleware ${middleware} not loaded`)
161
+ throw new Error(`Middleware ${middleware} not loaded`)
162
+ }
163
+ return required
142
164
  }
143
165
 
166
+ async function loadMiddlewares(base: string, middlewares: string[] = []) {
167
+ const midds = {}
168
+ await Promise.all(
169
+ middlewares.map(async (m) => {
170
+ const middleware = await loadMiddleware(base, m)
171
+ Object.keys(middleware).map((name) => (midds[name] = [...(midds[name] || []), middleware[name]]))
172
+ })
173
+ )
174
+ // log.debug(base + ' middleware ' + middlewares.length + ' -> ' + Object.keys(midds))
175
+ return midds
176
+ }
177
+
178
+ // preParsing, preValidation, preHandler, preSerialization, ..
179
+
144
180
  export function apply(server: any, routes: ConfiguredRoute[]): void {
145
181
  log.t && log.trace(`Apply ${routes.length} routes to server with pid ${process.pid}`)
146
182
 
147
183
  routes.forEach(async ({ handler, method, path, middlewares, roles, enable, base, file, func, doc }) => {
148
184
  if (enable) {
149
185
  log.t && log.trace(`* Add path ${method} ${path} on handle ${handler}`)
186
+ const midds = await loadMiddlewares(base, middlewares)
150
187
 
151
188
  server.route({
152
189
  method: method,
153
190
  path: path,
154
191
  schema: doc,
155
- preHandler: (middlewares || []).map((m) => require(normalizeMiddlewarePath(base, m))),
192
+ ...midds,
156
193
  config: {
157
194
  requiredRoles: roles || []
158
195
  },
@@ -15,9 +15,13 @@ export function apply(server: any): void {
15
15
  schemaNames.map((name) => {
16
16
  const schema = schemaClass[name]
17
17
  if (schema != null) {
18
- log.trace(`* Schema [${schema.$id}] loaded from ${schemaFileName}`)
19
- server.addSchema(schema)
20
- schemaCount++
18
+ if (schema?.$id) {
19
+ log.trace(`* Schema [${schema.$id}] loaded from ${schemaFileName}`)
20
+ server.addSchema(schema)
21
+ schemaCount++
22
+ } else {
23
+ log.warn(`* Schema [${schema.$id}] not loaded from ${schemaFileName}`)
24
+ }
21
25
  }
22
26
  })
23
27
  })
@@ -1,11 +1,11 @@
1
1
  import { FastifyReply, FastifyRequest } from 'fastify'
2
2
 
3
- const log = global.log
4
- module.exports = (req: FastifyRequest, res: FastifyReply, next: any) => {
3
+ export function preHandler(req: FastifyRequest, res: FastifyReply, done: any) {
5
4
  try {
6
5
  if (req.user && req.user.id && req.hasRole(roles.admin)) {
7
- return next()
6
+ return done()
8
7
  }
8
+
9
9
  throw new Error('User without this privilege')
10
10
  } catch (err) {
11
11
  log.e && log.error(`Upps, something just happened ${err}`)
@@ -1,14 +1,14 @@
1
1
  import { FastifyReply, FastifyRequest } from 'fastify'
2
2
 
3
- const log = global.log
4
- module.exports = (req: FastifyRequest, res: FastifyReply, next: any) => {
3
+ export function preHandler(req: FastifyRequest, res: FastifyReply, done: any) {
5
4
  try {
6
5
  if (!!req.user?.id) {
7
- return next()
6
+ return done()
8
7
  }
9
- throw new Error('User not authenticated')
8
+
9
+ throw new Error('Unauthorized')
10
10
  } catch (err) {
11
11
  log.e && log.error(`Upps, something just happened ${err}`)
12
- res.code(403).send(err)
12
+ return res.code(401).send(err) // must be authorized first
13
13
  }
14
14
  }
@@ -0,0 +1,5 @@
1
+ import { FastifyReply, FastifyRequest } from 'fastify'
2
+
3
+ export async function preSerialization(req: FastifyRequest, res: FastifyReply, payload) {
4
+ return payload
5
+ }
@@ -0,0 +1,3 @@
1
+ import { FastifyReply, FastifyRequest } from 'fastify'
2
+
3
+ export async function preHandler(req: FastifyRequest, res: FastifyReply) {}
@@ -0,0 +1,6 @@
1
+ const { customAlphabet } = require('nanoid')
2
+ const nanoid = customAlphabet('AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789')
3
+
4
+ export function newAuthCode() {
5
+ return nanoid(Number(process.env.AUTH_CODE_SIZE) || 10)
6
+ }
@@ -1,32 +1,34 @@
1
- module.exports = {
2
- /*
3
- * min 3 max 33, one special character (. _ -) only in the middle
4
- * username can have uppercase or lowercase chars
5
- */
6
- username: /(?=^.{3,33}$)^[a-z][a-z0-9]*[._-]?[a-z0-9]+$/gi,
7
- emailAlt:
8
- /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
9
- /*
10
- * email can have multiple words
11
- * email can use . - or + for smart labeling
12
- */
13
- email: /^\w+([\.+-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/,
14
- /*
15
- * password must contain 1 number (0-9)
16
- * password must contain 1 uppercase chars
17
- * password must contain 1 lowercase chars
18
- * password must contain 1 non-alpha number
19
- * password is 8-64 characters with no space
20
- */
21
- password: /^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[^\w\d\s:])([^\s]){8,64}$/gi,
22
- zipCode: /(^\d{5}$)|(^\d{5}-\d{4}$)/,
23
- taxCodePersona: /^[a-zA-Z]{6}[0-9]{2}[abcdehlmprstABCDEHLMPRST]{1}[0-9]{2}([a-zA-Z]{1}[0-9]{3})[a-zA-Z]{1}$/,
24
- /*
25
- * taxCode can have 2 letter (IT,DE,..) and 11 digits
26
- */
27
- taxCodeCompany: /^([A-Z]{2}|)[0-9]{11}$/,
28
- iban: /^[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}$/,
29
- mobilePhone: /^((00|\+)39)?3[0-9]{8,9}$/,
30
- landLinePhone: /^(((00|\+)39))?[\s]?(0{1}[1-9]{1,3})[\s]?(\d{4,6})$/,
31
- tollFreePhone: /^((00|\+)39)?(800|803|167)\d{3,6}$/
32
- }
1
+ /*
2
+ * min 3 max 33, one special character (. _ -) only in the middle
3
+ * username can have uppercase or lowercase chars
4
+ */
5
+ export const username = /(?=^.{3,33}$)^[a-z][a-z0-9]*[._-]?[a-z0-9]+$/gi
6
+ export const emailAlt =
7
+ /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
8
+
9
+ /*
10
+ * email can have multiple words
11
+ * email can use . - or + for smart labeling
12
+ */
13
+ export const email = /^\w+([\.+-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/
14
+
15
+ /*
16
+ * password must contain 1 number (0-9)
17
+ * password must contain 1 uppercase chars
18
+ * password must contain 1 lowercase chars
19
+ * password must contain 1 non-alpha number
20
+ * password is 8-64 characters with no space
21
+ */
22
+ export const password = /^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[^\w\d\s:])([^\s]){8,16}$/
23
+ export const zipCode = /(^\d{5}$)|(^\d{5}-\d{4}$)/
24
+ export const taxCodePersona =
25
+ /^[a-zA-Z]{6}[0-9]{2}[abcdehlmprstABCDEHLMPRST]{1}[0-9]{2}([a-zA-Z]{1}[0-9]{3})[a-zA-Z]{1}$/
26
+
27
+ /*
28
+ * taxCode can have 2 letter (IT,DE,..) and 11 digits
29
+ */
30
+ export const taxCodeCompany = /^([A-Z]{2}|)[0-9]{11}$/
31
+ export const iban = /^[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}$/
32
+ export const mobilePhone = /^((00|\+)39)?3[0-9]{8,9}$/
33
+ export const landLinePhone = /^(((00|\+)39))?[\s]?(0{1}[1-9]{1,3})[\s]?(\d{4,6})$/
34
+ export const tollFreePhone = /^((00|\+)39)?(800|803|167)\d{3,6}$/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volcanicminds/backend",
3
- "version": "0.2.28",
3
+ "version": "0.2.29",
4
4
  "codename": "turin",
5
5
  "license": "MIT",
6
6
  "description": "The volcanic (minds) backend",
package/types/global.d.ts CHANGED
@@ -2,7 +2,7 @@ import { FastifyRequest, FastifyReply } from 'fastify'
2
2
 
3
3
  export interface AuthenticatedUser {
4
4
  id: number
5
- name: string
5
+ username: string
6
6
  email: string
7
7
  roles: Role[]
8
8
  }
@@ -68,6 +68,20 @@ export interface ConfiguredRoute {
68
68
  }
69
69
  }
70
70
 
71
+ export interface UserManagement {
72
+ createUser(data: any): any | null
73
+ resetExternalId(data: any): any | null
74
+ updateUserById(id: string, user: any): any | null
75
+ retrieveUserById(id: string): any | null
76
+ retrieveUserByEmail(email: string): any | null
77
+ retrieveUserByExternalId(externalId: string): any | null
78
+ retrieveUserByPassword(email: string, password: string): any | null
79
+ changePassword(email: string, password: string, oldPassword: string): any | null
80
+ enableUserById(id: string): any | null
81
+ disableUserById(id: string): any | null
82
+ isValidUser(data: any): boolean
83
+ }
84
+
71
85
  declare module 'fastify' {
72
86
  export interface FastifyRequest {
73
87
  user?: AuthenticatedUser