@volcanicminds/backend 0.2.43 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +13 -1
  2. package/dist/index.js +8 -3
  3. package/dist/index.js.map +1 -1
  4. package/dist/lib/api/auth/controller/auth.js +15 -17
  5. package/dist/lib/api/auth/controller/auth.js.map +1 -1
  6. package/dist/lib/api/auth/routes.js +1 -1
  7. package/dist/lib/api/auth/routes.js.map +1 -1
  8. package/dist/lib/api/token/controller/token.js +1 -1
  9. package/dist/lib/api/token/controller/token.js.map +1 -1
  10. package/dist/lib/api/token/routes.js +2 -2
  11. package/dist/lib/api/token/routes.js.map +1 -1
  12. package/dist/lib/loader/hooks.js +2 -1
  13. package/dist/lib/loader/hooks.js.map +1 -1
  14. package/dist/lib/loader/plugins.js +2 -1
  15. package/dist/lib/loader/plugins.js.map +1 -1
  16. package/dist/lib/loader/roles.js +2 -1
  17. package/dist/lib/loader/roles.js.map +1 -1
  18. package/dist/lib/loader/router.js +2 -1
  19. package/dist/lib/loader/router.js.map +1 -1
  20. package/dist/lib/loader/schemas.js +2 -1
  21. package/dist/lib/loader/schemas.js.map +1 -1
  22. package/dist/lib/middleware/isAdmin.js +1 -1
  23. package/dist/lib/middleware/isAdmin.js.map +1 -1
  24. package/dist/lib/middleware/isAuthenticated.js +1 -1
  25. package/dist/lib/middleware/isAuthenticated.js.map +1 -1
  26. package/dist/lib/middleware/preForgotPasswordHandler.js +17 -0
  27. package/dist/lib/middleware/preForgotPasswordHandler.js.map +1 -0
  28. package/dist/lib/schemas/token.js +13 -3
  29. package/dist/lib/schemas/token.js.map +1 -1
  30. package/dist/lib/util/path.js +12 -0
  31. package/dist/lib/util/path.js.map +1 -0
  32. package/index.ts +35 -14
  33. package/lib/api/auth/controller/auth.ts +76 -16
  34. package/lib/api/auth/routes.ts +17 -14
  35. package/lib/api/token/controller/token.ts +1 -1
  36. package/lib/api/token/routes.ts +2 -2
  37. package/lib/config/plugins.ts +35 -2
  38. package/lib/loader/hooks.ts +3 -1
  39. package/lib/loader/plugins.ts +2 -1
  40. package/lib/loader/roles.ts +2 -1
  41. package/lib/loader/router.ts +2 -1
  42. package/lib/loader/schemas.ts +3 -1
  43. package/lib/middleware/isAdmin.ts +1 -1
  44. package/lib/middleware/isAuthenticated.ts +1 -1
  45. package/lib/middleware/preForgotPasswordHandler.ts +3 -0
  46. package/lib/schemas/auth.ts +36 -0
  47. package/lib/schemas/token.ts +13 -2
  48. package/lib/util/path.ts +8 -0
  49. package/logo-dark.png +0 -0
  50. package/nodemon.json +7 -0
  51. package/package.json +1 -2
  52. package/types/global.d.ts +2 -0
  53. package/jest.config.js +0 -188
  54. package/nodemon.json +0 -15
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../../../lib/util/path.ts"],"names":[],"mappings":";;;AAAA,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AAC5B,SAAgB,iBAAiB,CAAC,KAAoB,EAAE,KAAoB;IAE1E,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC;KACzD,CAAA;AACH,CAAC;AAND,8CAMC"}
package/index.ts CHANGED
@@ -78,6 +78,9 @@ async function addFastifySwagger(fastify: FastifyInstance) {
78
78
  if (loadSwagger) {
79
79
  log.trace('Add swagger plugin')
80
80
 
81
+ const fs = require('fs')
82
+ const contents = fs.readFileSync('logo-dark.png', { encoding: 'base64' })
83
+
81
84
  await fastify.register(swagger, {
82
85
  swagger: {
83
86
  info: {
@@ -118,17 +121,14 @@ async function addFastifySwagger(fastify: FastifyInstance) {
118
121
  docExpansion: 'list',
119
122
  deepLinking: true,
120
123
  defaultModelsExpandDepth: 1
124
+ },
125
+ logo: {
126
+ type: 'image/png',
127
+ content: Buffer.from(contents, 'base64')
128
+ },
129
+ theme: {
130
+ title: SWAGGER_TITLE
121
131
  }
122
- // uiHooks: {
123
- // onRequest: function (request, reply, next) {
124
- // next()
125
- // },
126
- // preHandler: function (request, reply, next) {
127
- // next()
128
- // }
129
- // }
130
- // staticCSP: true,
131
- // transformStaticCSP: (header) => header
132
132
  })
133
133
  }
134
134
  }
@@ -142,8 +142,15 @@ const start = async (decorators) => {
142
142
  const fastify = await Fastify(opts)
143
143
 
144
144
  const { HOST: host = '0.0.0.0', PORT: port = '2230', GRAPHQL } = process.env
145
- const { JWT_SECRET, JWT_EXPIRES_IN = '15d' } = process.env
146
-
145
+ const {
146
+ JWT_SECRET = '',
147
+ JWT_EXPIRES_IN = '15d',
148
+ JWT_REFRESH = 'true',
149
+ JWT_REFRESH_SECRET = '',
150
+ JWT_REFRESH_EXPIRES_IN = '180d'
151
+ } = process.env
152
+
153
+ const loadRefreshJWT = yn(JWT_REFRESH, true)
147
154
  const loadApollo = yn(GRAPHQL, false)
148
155
  const plugins = loaderPlugins.load()
149
156
 
@@ -156,10 +163,18 @@ const start = async (decorators) => {
156
163
  // JWT Validator
157
164
  log.t && log.trace(`Add JWT - expiresIn: ${JWT_EXPIRES_IN}`)
158
165
  await fastify.register(jwtValidator, {
159
- secret: JWT_SECRET || 'supersecret',
166
+ secret: JWT_SECRET,
160
167
  sign: { expiresIn: JWT_EXPIRES_IN }
161
168
  })
162
169
 
170
+ if (loadRefreshJWT) {
171
+ await fastify.register(jwtValidator, {
172
+ namespace: 'refreshToken',
173
+ secret: JWT_REFRESH_SECRET || JWT_SECRET,
174
+ sign: { expiresIn: JWT_REFRESH_EXPIRES_IN }
175
+ })
176
+ }
177
+
163
178
  const apollo = loadApollo ? await attachApollo(fastify) : null
164
179
  await addFastifySwagger(fastify)
165
180
  await addApolloRouting(fastify, apollo)
@@ -168,6 +183,9 @@ const start = async (decorators) => {
168
183
  // defaults
169
184
  decorators = {
170
185
  userManager: {
186
+ isImplemented() {
187
+ return false
188
+ },
171
189
  isValidUser(data: any) {
172
190
  throw Error('Not implemented')
173
191
  },
@@ -207,7 +225,7 @@ const start = async (decorators) => {
207
225
  forgotPassword(email: string) {
208
226
  throw Error('Not implemented')
209
227
  },
210
- userConfirmation(email: string) {
228
+ userConfirmation(user: any) {
211
229
  throw Error('Not implemented')
212
230
  },
213
231
  resetPassword(user: any, password: string) {
@@ -227,6 +245,9 @@ const start = async (decorators) => {
227
245
  }
228
246
  } as UserManagement,
229
247
  tokenManager: {
248
+ isImplemented() {
249
+ return false
250
+ },
230
251
  isValidToken(data: any) {
231
252
  throw Error('Not implemented')
232
253
  },
@@ -4,31 +4,32 @@ import * as regExp from '../../../util/regexp'
4
4
  export async function register(req: FastifyRequest, reply: FastifyReply) {
5
5
  const { password1: password, password2, ...data } = req.data()
6
6
 
7
+ if (!req.server['userManager'].isImplemented()) {
8
+ throw Error('Not implemented')
9
+ }
10
+
7
11
  if (!data.username) {
8
- return reply.status(404).send(Error('Username not valid'))
12
+ return reply.status(400).send(Error('Username not valid'))
9
13
  }
10
14
  if (!data.email || !regExp.email.test(data.email)) {
11
- return reply.status(404).send(Error('Email not valid'))
15
+ return reply.status(400).send(Error('Email not valid'))
12
16
  }
13
17
  if (!password || !regExp.password.test(password)) {
14
- return reply.status(404).send(Error('Password not valid'))
18
+ return reply.status(400).send(Error('Password not valid'))
15
19
  }
16
20
  if (!password2 || password2 !== password) {
17
- return reply.status(404).send(Error('Repeated password not match'))
21
+ return reply.status(400).send(Error('Repeated password not match'))
18
22
  }
19
23
 
20
24
  let existings = await req.server['userManager'].retrieveUserByEmail(data.email)
21
25
  if (existings) {
22
- return reply.status(404).send(Error('Email already registered'))
26
+ return reply.status(400).send(Error('Email already registered'))
23
27
  }
24
28
 
25
- console.log('role ' + data.requiredRoles)
26
29
  if ((data.requiredRoles || []).includes('admin')) {
27
- console.log('requiredRoles ' + data.requiredRoles)
28
30
  existings = await req.server['userManager'].findQuery({ 'roles:in': 'admin' })
29
- console.log('existings ' + existings)
30
- if (existings) {
31
- return reply.status(404).send(Error('User admin already registered'))
31
+ if (existings?.records?.length) {
32
+ return reply.status(400).send(Error('User admin already registered'))
32
33
  }
33
34
  }
34
35
 
@@ -89,6 +90,10 @@ export async function validatePassword(req: FastifyRequest, reply: FastifyReply)
89
90
  export async function changePassword(req: FastifyRequest, reply: FastifyReply) {
90
91
  const { email, oldPassword, newPassword1, newPassword2 } = req.data()
91
92
 
93
+ if (!req.server['userManager'].isImplemented()) {
94
+ throw Error('Not implemented')
95
+ }
96
+
92
97
  if (!newPassword1 || !regExp.password.test(newPassword1)) {
93
98
  return reply.status(400).send(Error('New password is not valid'))
94
99
  }
@@ -116,6 +121,10 @@ export async function changePassword(req: FastifyRequest, reply: FastifyReply) {
116
121
  export async function forgotPassword(req: FastifyRequest, reply: FastifyReply) {
117
122
  const { username, email } = req.data()
118
123
 
124
+ if (!req.server['userManager'].isImplemented()) {
125
+ throw Error('Not implemented')
126
+ }
127
+
119
128
  if (!username && (!email || (email && !regExp.email.test(email)))) {
120
129
  return reply.status(400).send(Error('Missing a valid user identifier'))
121
130
  }
@@ -170,6 +179,10 @@ export async function confirmEmail(req: FastifyRequest, reply: FastifyReply) {
170
179
  export async function resetPassword(req: FastifyRequest, reply: FastifyReply) {
171
180
  const { code, newPassword1, newPassword2 } = req.data()
172
181
 
182
+ if (!req.server['userManager'].isImplemented()) {
183
+ throw Error('Not implemented')
184
+ }
185
+
173
186
  if (!newPassword1 || !regExp.password.test(newPassword1)) {
174
187
  return reply.status(400).send(Error('New password not valid'))
175
188
  }
@@ -197,15 +210,21 @@ export async function resetPassword(req: FastifyRequest, reply: FastifyReply) {
197
210
  export async function login(req: FastifyRequest, reply: FastifyReply) {
198
211
  const { email, password } = req.data()
199
212
 
213
+ if (!req.server['userManager'].isImplemented()) {
214
+ throw Error('Not implemented')
215
+ }
216
+
200
217
  if (!email || !regExp.email.test(email)) {
201
- return reply.status(404).send(Error('Email not valid'))
218
+ return reply.status(400).send(Error('Email not valid'))
202
219
  }
203
220
  if (!password || !regExp.password.test(password)) {
204
- return reply.status(404).send(Error('Password not valid'))
221
+ return reply.status(400).send(Error('Password not valid'))
205
222
  }
206
223
 
207
224
  const user = await req.server['userManager'].retrieveUserByPassword(email, password)
208
225
  const isValid = await req.server['userManager'].isValidUser(user)
226
+ // const user = { confirmed: true, blocked: false, externalId: 123456, roles: [{ code: 'admin' }] }
227
+ // const isValid = true
209
228
 
210
229
  if (!isValid) {
211
230
  return reply.status(403).send(Error('Wrong credentials'))
@@ -219,13 +238,46 @@ export async function login(req: FastifyRequest, reply: FastifyReply) {
219
238
  return reply.status(403).send(Error('User blocked'))
220
239
  }
221
240
 
222
- // log.trace('User: ' + JSON.stringify(user) + ' ' + roles)
223
241
  // https://www.iana.org/assignments/jwt/jwt.xhtml
224
- const token = user !== null ? await reply.jwtSign({ sub: user.externalId }) : null
242
+ const token = await reply.jwtSign({ sub: user.externalId })
243
+ const refreshToken = reply.server.jwt['refreshToken']
244
+ ? await reply.server.jwt['refreshToken'].sign({ sub: user.externalId })
245
+ : undefined
246
+
225
247
  return {
226
248
  ...user,
227
- token: token || null,
228
- roles: (user.roles || [global.role?.public?.code || 'public']).map((r) => r?.code || r)
249
+ roles: (user.roles || [global.role?.public?.code || 'public']).map((r) => r?.code || r),
250
+ token: token,
251
+ refreshToken
252
+ }
253
+ }
254
+
255
+ export async function refreshToken(req: FastifyRequest, reply: FastifyReply) {
256
+ const { token, refreshToken } = req.data()
257
+
258
+ if (!req.server['userManager'].isImplemented()) {
259
+ throw Error('Not implemented')
260
+ }
261
+
262
+ const tokenData = (await reply.server.jwt.decode(token)) as any
263
+ const refreshTokenData = await reply.server.jwt['refreshToken'].verify(refreshToken)
264
+
265
+ if (tokenData?.sub && tokenData?.sub !== refreshTokenData?.sub) {
266
+ return reply.status(403).send(Error('Mismatched tokens'))
267
+ }
268
+
269
+ const user = await req.server['userManager'].retrieveUserByExternalId(tokenData?.sub)
270
+ const isValid = await req.server['userManager'].isValidUser(user)
271
+ // const user = { confirmed: true, blocked: false, externalId: 123456, roles: [{ code: 'admin' }] }
272
+ // const isValid = true
273
+
274
+ if (!isValid) {
275
+ return reply.status(403).send(Error('Wrong refresh token'))
276
+ }
277
+
278
+ const newToken = await reply.jwtSign({ sub: user.externalId })
279
+ return {
280
+ token: newToken
229
281
  }
230
282
  }
231
283
 
@@ -241,6 +293,10 @@ export async function invalidateTokens(req: FastifyRequest, reply: FastifyReply)
241
293
  }
242
294
 
243
295
  export async function block(req: FastifyRequest, reply: FastifyReply) {
296
+ if (!req.server['userManager'].isImplemented()) {
297
+ throw Error('Not implemented')
298
+ }
299
+
244
300
  if (!req.hasRole(roles.admin) && !req.hasRole(roles.backoffice)) {
245
301
  return reply.status(403).send({ statusCode: 403, code: 'ROLE_NOT_ALLOWED', message: 'Not allowed to block a user' })
246
302
  }
@@ -253,6 +309,10 @@ export async function block(req: FastifyRequest, reply: FastifyReply) {
253
309
  }
254
310
 
255
311
  export async function unblock(req: FastifyRequest, reply: FastifyReply) {
312
+ if (!req.server['userManager'].isImplemented()) {
313
+ throw Error('Not implemented')
314
+ }
315
+
256
316
  if (!req.hasRole(roles.admin) && !req.hasRole(roles.backoffice)) {
257
317
  return reply
258
318
  .status(403)
@@ -74,7 +74,7 @@ module.exports = {
74
74
  path: '/forgot-password',
75
75
  roles: [],
76
76
  handler: 'auth.forgotPassword',
77
- middlewares: ['global.dispatchForgotPasswordLink'],
77
+ middlewares: ['global.preForgotPasswordHandler', 'global.dispatchForgotPasswordLink'],
78
78
  config: {
79
79
  title: 'Forgot password',
80
80
  description: 'Forgot password for an existing user given the email or username',
@@ -125,19 +125,22 @@ module.exports = {
125
125
  description: 'Basic login authentication',
126
126
  body: { $ref: 'authLoginBodySchema#' },
127
127
  response: {
128
- 200: {
129
- description: 'Default response',
130
- type: 'object',
131
- properties: {
132
- id: { type: 'string' },
133
- _id: { type: 'string' },
134
- externalId: { type: 'string' },
135
- username: { type: 'string' },
136
- email: { type: 'string' },
137
- roles: { type: 'array', items: { type: 'string' } },
138
- token: { type: 'string' }
139
- }
140
- }
128
+ 200: { $ref: 'authLoginResponseSchema#' }
129
+ }
130
+ }
131
+ },
132
+ {
133
+ method: 'POST',
134
+ path: '/refresh-token',
135
+ roles: [],
136
+ handler: 'auth.refreshToken',
137
+ middlewares: [],
138
+ config: {
139
+ title: 'Refresh authentication token',
140
+ description: 'Refresh login authentication token',
141
+ body: { $ref: 'authRefreshTokenBodySchema#' },
142
+ response: {
143
+ 200: { $ref: 'authRefreshTokenResponseSchema#' }
141
144
  }
142
145
  }
143
146
  },
@@ -38,7 +38,7 @@ export async function create(req: FastifyRequest, reply: FastifyReply) {
38
38
  const bearerToken = await reply.jwtSign(
39
39
  { sub: token.externalId },
40
40
  {
41
- sign: { expiresIn: undefined }
41
+ sign: { expiresIn: data?.expiresIn || undefined }
42
42
  }
43
43
  )
44
44
  if (!bearerToken) {
@@ -72,7 +72,7 @@ module.exports = {
72
72
  config: {
73
73
  title: 'Create new token',
74
74
  description: 'Create a new token',
75
- body: { $ref: 'tokenBodySchema' },
75
+ body: { $ref: 'tokenCreateBodySchema' },
76
76
  response: {
77
77
  200: {
78
78
  description: 'Default response',
@@ -91,7 +91,7 @@ module.exports = {
91
91
  title: 'Update existing token',
92
92
  description: 'Update an existing token',
93
93
  params: { $ref: 'onlyIdSchema#' },
94
- body: { $ref: 'tokenBodySchema' },
94
+ body: { $ref: 'tokenUpdateBodySchema' },
95
95
  response: {
96
96
  200: {
97
97
  description: 'Default response',
@@ -3,8 +3,41 @@
3
3
  module.exports = [
4
4
  {
5
5
  name: 'cors',
6
- enable: false,
7
- options: {}
6
+ enable: true,
7
+ options: {
8
+ origin: '*',
9
+ methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'],
10
+ maxAge: 31536000,
11
+ credentials: true,
12
+ allowedHeaders: [
13
+ 'Accept',
14
+ 'Accept-Language',
15
+ 'Content-Language',
16
+ 'Content-Type',
17
+ 'Content-Length',
18
+ 'Authorization',
19
+ 'Origin',
20
+ 'v-total',
21
+ 'v-count',
22
+ 'v-page',
23
+ 'v-pageSize',
24
+ 'v-pageCount'
25
+ ],
26
+ exposedHeaders: [
27
+ 'Accept',
28
+ 'Accept-Language',
29
+ 'Content-Language',
30
+ 'Content-Type',
31
+ 'Content-Length',
32
+ 'Authorization',
33
+ 'Origin',
34
+ 'v-total',
35
+ 'v-count',
36
+ 'v-page',
37
+ 'v-pageSize',
38
+ 'v-pageCount'
39
+ ]
40
+ }
8
41
  },
9
42
  {
10
43
  name: 'rateLimit',
@@ -1,3 +1,5 @@
1
+ import { normalizePatterns } from '../util/path'
2
+
1
3
  const hooks = [
2
4
  'onRequest',
3
5
  'onError',
@@ -18,7 +20,7 @@ const glob = require('glob')
18
20
  const path = require('path')
19
21
 
20
22
  export function apply(server: any): void {
21
- const patterns = [`${__dirname}/../hooks/*.{ts,js}`, `${process.cwd()}/src/hooks/*.{ts,js}`]
23
+ const patterns = normalizePatterns(['..', 'hooks', '*.{ts,js}'], ['src', 'hooks', '*.{ts,js}'])
22
24
  const allHooks: any = hooks.reduce((acc, v) => ({ ...acc, [v]: [] as Function[] }), {})
23
25
 
24
26
  patterns.forEach((pattern) => {
@@ -1,11 +1,12 @@
1
1
  import { config } from 'dotenv'
2
+ import { normalizePatterns } from '../util/path'
2
3
 
3
4
  const glob = require('glob')
4
5
 
5
6
  export function load() {
6
7
  const plugins: any = {}
7
8
 
8
- const patterns = [`${__dirname}/../config/plugins.{ts,js}`, `${process.cwd()}/src/config/plugins.{ts,js}`]
9
+ const patterns = normalizePatterns(['..', 'config', 'plugins.{ts,js}'], ['src', 'config', 'plugins.{ts,js}'])
9
10
  patterns.forEach((pattern) => {
10
11
  log.t && log.trace('Looking for ' + pattern)
11
12
  glob.sync(pattern).forEach((f: string) => {
@@ -1,10 +1,11 @@
1
1
  import { Role, Roles } from '../../types/global'
2
+ import { normalizePatterns } from '../util/path'
2
3
  const glob = require('glob')
3
4
 
4
5
  export function load() {
5
6
  const roles: Roles = {}
6
7
 
7
- const patterns = [`${__dirname}/../config/roles.{ts,js}`, `${process.cwd()}/src/config/roles.{ts,js}`]
8
+ const patterns = normalizePatterns(['..', 'config', 'roles.{ts,js}'], ['src', 'config', 'roles.{ts,js}'])
8
9
  patterns.forEach((pattern) => {
9
10
  log.t && log.trace('Looking for ' + pattern)
10
11
  glob.sync(pattern).forEach((f: string) => {
@@ -1,6 +1,7 @@
1
1
  import yn from '../util/yn'
2
2
  import { Route, ConfiguredRoute, RouteConfig } from '../../types/global'
3
3
  import { FastifyReply, FastifyRequest } from 'fastify'
4
+ import { normalizePatterns } from '../util/path'
4
5
 
5
6
  const glob = require('glob')
6
7
  const path = require('path')
@@ -8,7 +9,7 @@ const methods = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'PATCH', 'OPTIONS']
8
9
 
9
10
  export function load(): ConfiguredRoute[] {
10
11
  const validRoutes: ConfiguredRoute[] = []
11
- const patterns = [`${__dirname}/../api/**/routes.{ts,js}`, `${process.cwd()}/src/api/**/routes.{ts,js}`]
12
+ const patterns = normalizePatterns(['..', 'api', '**', 'routes.{ts,js}'], ['src', 'api', '**', 'routes.{ts,js}'])
12
13
  const authMiddlewares = ['global.isAuthenticated', 'global.isAdmin']
13
14
 
14
15
  patterns.forEach((pattern) => {
@@ -1,8 +1,10 @@
1
+ import { normalizePatterns } from '../util/path'
2
+
1
3
  const glob = require('glob')
2
4
  const path = require('path')
3
5
 
4
6
  export function apply(server: any): void {
5
- const patterns = [`${__dirname}/../schemas/*.{ts,js}`, `${process.cwd()}/src/schemas/*.{ts,js}`]
7
+ const patterns = normalizePatterns(['..', 'schemas', '*.{ts,js}'], ['src', 'schemas', '*.{ts,js}'])
6
8
 
7
9
  let schemaCount = 0
8
10
  patterns.forEach((pattern) => {
@@ -9,6 +9,6 @@ export function preHandler(req: FastifyRequest, res: FastifyReply, done: any) {
9
9
  throw new Error('User without this privilege')
10
10
  } catch (err) {
11
11
  log.e && log.error(`Upps, something just happened ${err}`)
12
- res.code(403).send(err)
12
+ res.code(403).send(new Error('User without this privilege'))
13
13
  }
14
14
  }
@@ -9,6 +9,6 @@ export function preHandler(req: FastifyRequest, res: FastifyReply, done: any) {
9
9
  throw new Error('Unauthorized')
10
10
  } catch (err) {
11
11
  log.e && log.error(`Upps, something just happened ${err}`)
12
- return res.code(401).send(err) // must be authorized first
12
+ return res.code(401).send(new Error('Unauthorized')) // must be authorized first
13
13
  }
14
14
  }
@@ -0,0 +1,3 @@
1
+ import { FastifyReply, FastifyRequest } from 'fastify'
2
+
3
+ export async function preHandler(req: FastifyRequest, res: FastifyReply) {}
@@ -7,6 +7,7 @@ export const authLoginBodySchema = {
7
7
  password: { type: 'string' }
8
8
  }
9
9
  }
10
+
10
11
  export const authForgotPasswordBodySchema = {
11
12
  $id: 'authForgotPasswordBodySchema',
12
13
  type: 'object',
@@ -30,6 +31,41 @@ export const authRegisterBodySchema = {
30
31
  }
31
32
  }
32
33
 
34
+ export const authLoginResponseSchema = {
35
+ $id: 'authLoginResponseSchema',
36
+ type: 'object',
37
+ nullable: true,
38
+ properties: {
39
+ id: { type: 'string' },
40
+ _id: { type: 'string' },
41
+ externalId: { type: 'string' },
42
+ username: { type: 'string' },
43
+ email: { type: 'string' },
44
+ roles: { type: 'array', items: { type: 'string' } },
45
+ token: { type: 'string' },
46
+ refreshToken: { type: 'string' }
47
+ }
48
+ }
49
+
50
+ export const authRefreshTokenBodySchema = {
51
+ $id: 'authRefreshTokenBodySchema',
52
+ type: 'object',
53
+ nullable: true,
54
+ properties: {
55
+ token: { type: 'string' },
56
+ refreshToken: { type: 'string' }
57
+ }
58
+ }
59
+
60
+ export const authRefreshTokenResponseSchema = {
61
+ $id: 'authRefreshTokenResponseSchema',
62
+ type: 'object',
63
+ nullable: true,
64
+ properties: {
65
+ token: { type: 'string' }
66
+ }
67
+ }
68
+
33
69
  export const authRegisterResponseSchema = {
34
70
  $id: 'authRegisterResponseSchema',
35
71
  type: 'object',
@@ -1,14 +1,25 @@
1
- export const tokenBodySchema = {
2
- $id: 'tokenBodySchema',
1
+ export const tokenCreateBodySchema = {
2
+ $id: 'tokenCreateBodySchema',
3
3
  type: 'object',
4
4
  nullable: true,
5
5
  properties: {
6
6
  name: { type: 'string' },
7
7
  description: { type: 'string' },
8
+ expiresIn: { type: 'string', default: undefined },
8
9
  requiredRoles: { type: 'array', items: { type: 'string' } }
9
10
  }
10
11
  }
11
12
 
13
+ export const tokenUpdateBodySchema = {
14
+ $id: 'tokenUpdateBodySchema',
15
+ type: 'object',
16
+ nullable: true,
17
+ properties: {
18
+ name: { type: 'string' },
19
+ description: { type: 'string' }
20
+ }
21
+ }
22
+
12
23
  export const tokenSchema = {
13
24
  $id: 'tokenSchema',
14
25
  type: 'object',
@@ -0,0 +1,8 @@
1
+ const path = require('path')
2
+ export function normalizePatterns(path1: Array<string>, path2: Array<string>): Array<string> {
3
+ // replaceAll is needed for windows
4
+ return [
5
+ path.join(__dirname, ...path1).replaceAll('\\', '/'),
6
+ path.join(process.cwd(), ...path2).replaceAll('\\', '/')
7
+ ]
8
+ }
package/logo-dark.png ADDED
Binary file
package/nodemon.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "watch": ["lib"],
3
+ "verbose": true,
4
+ "ext": "js,ts,json,jsonc",
5
+ "ignore": [".git", "coverage", "dist", "lib/**/*.spec.ts", "node_modules"],
6
+ "exec": "ts-node ./lib/index.ts"
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volcanicminds/backend",
3
- "version": "0.2.43",
3
+ "version": "0.3.1",
4
4
  "codename": "turin",
5
5
  "license": "MIT",
6
6
  "description": "The volcanic (minds) backend",
@@ -71,7 +71,6 @@
71
71
  "semver": "^7.3.8"
72
72
  },
73
73
  "devDependencies": {
74
- "jest": "^29.3.1",
75
74
  "nodemon": "^2.0.20",
76
75
  "ts-node": "^10.9.1",
77
76
  "typescript": "^4.9.3"
package/types/global.d.ts CHANGED
@@ -75,6 +75,7 @@ export interface ConfiguredRoute {
75
75
  }
76
76
 
77
77
  export interface UserManagement {
78
+ isImplemented(): boolean
78
79
  isValidUser(data: any): boolean
79
80
  createUser(data: any): any | null
80
81
  resetExternalId(data: any): any | null
@@ -97,6 +98,7 @@ export interface UserManagement {
97
98
  }
98
99
 
99
100
  export interface TokenManagement {
101
+ isImplemented(): boolean
100
102
  isValidToken(data: any): boolean
101
103
  createToken(data: any): any | null
102
104
  resetExternalId(id: string): any | null