@volcanicminds/backend 1.0.4 → 2.0.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.
package/dist/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@volcanicminds/backend",
3
- "version": "1.0.4",
4
- "codename": "turin",
3
+ "version": "2.0.1",
4
+ "codename": "rome",
5
5
  "license": "MIT",
6
6
  "description": "The volcanic (minds) backend",
7
7
  "keywords": [
@@ -29,9 +29,6 @@
29
29
  ],
30
30
  "main": "dist/index",
31
31
  "typings": "dist/index",
32
- "engines": {
33
- "node": ">=16"
34
- },
35
32
  "scripts": {
36
33
  "clean": "rm -rf dist esm",
37
34
  "prebuild": "npm run clean",
@@ -44,51 +41,50 @@
44
41
  "server": "cd dist && node server.js",
45
42
  "start": "ts-node server.ts",
46
43
  "dev": "nodemon --exec \"ts-node\" server.ts",
47
- "test": "yarn test:full",
44
+ "test": "npm run test:full",
48
45
  "test:full": "cross-env PORT=2231 NODE_ENV=memory BROWSER=false mocha ./test/index.spec.ts -t 100000",
49
- "reset": "yarn && yarn up && yarn compile",
50
- "upgrade-deps": "yarn upgrade-interactive",
51
- "upgrade-pkg": "yarn npm-upgrade",
46
+ "reset": "npm install && npm update && npm run compile",
47
+ "upgrade-deps": "npx npm-check-updates -u",
52
48
  "combine": "node combine.js"
53
49
  },
54
50
  "dependencies": {
55
- "@apollo/server": "^4.11.0",
56
- "@as-integrations/fastify": "^2.1.1",
57
- "@fastify/compress": "^7.0.3",
58
- "@fastify/cors": "^9.0.1",
59
- "@fastify/helmet": "^11.1.1",
60
- "@fastify/jwt": "^8.0.1",
61
- "@fastify/multipart": "^8.3.0",
62
- "@fastify/rate-limit": "^9.1.0",
63
- "@fastify/schedule": "^4.1.1",
64
- "@fastify/swagger": "^8.15.0",
65
- "@fastify/swagger-ui": "^3.1.0",
66
- "@types/node": "^20.17.0",
67
- "dayjs": "^1.11.13",
68
- "dotenv": "^16.4.5",
69
- "fastify": "^4.28.1",
70
- "fastify-raw-body": "^4.3.0",
71
- "glob": "^10.4.5",
72
- "graphql": "^16.9.0",
73
- "i18n": "^0.15.1",
51
+ "@apollo/server": "^5.1.0",
52
+ "@as-integrations/fastify": "^3.1.0",
53
+ "@fastify/compress": "^8.1.0",
54
+ "@fastify/cors": "^11.1.0",
55
+ "@fastify/helmet": "^13.0.2",
56
+ "@fastify/jwt": "^10.0.0",
57
+ "@fastify/multipart": "^9.3.0",
58
+ "@fastify/rate-limit": "^10.3.0",
59
+ "@fastify/schedule": "^6.0.0",
60
+ "@fastify/swagger": "^9.5.2",
61
+ "@fastify/swagger-ui": "^5.2.3",
62
+ "@types/node": "^24.10.0",
63
+ "dayjs": "^1.11.19",
64
+ "dotenv": "^17.2.3",
65
+ "fastify": "^5.6.1",
66
+ "fastify-raw-body": "^5.0.0",
67
+ "glob": "^11.0.3",
68
+ "graphql": "^16.12.0",
69
+ "i18n": "^0.15.3",
74
70
  "lodash": "^4.17.21",
75
- "nanoid": "^5.0.7",
71
+ "nanoid": "^5.1.6",
76
72
  "object-sizeof": "^2.6.5",
77
- "pino": "^9.5.0",
78
- "pino-pretty": "^11.3.0",
73
+ "pino": "^10.1.0",
74
+ "pino-pretty": "^13.1.2",
79
75
  "root-require": "^0.3.1",
80
- "semver": "^7.6.3",
81
- "toad-scheduler": "^3.0.1"
76
+ "semver": "^7.7.3",
77
+ "toad-scheduler": "^3.1.0"
82
78
  },
83
79
  "devDependencies": {
84
- "@types/mocha": "^10.0.9",
85
- "cross-env": "^7.0.3",
86
- "expect": "^29.7.0",
87
- "mocha": "^10.7.3",
88
- "nodemon": "^3.1.7",
89
- "npm-upgrade": "^3.1.0",
80
+ "@types/mocha": "^10.0.10",
81
+ "cross-env": "^10.1.0",
82
+ "expect": "^30.2.0",
83
+ "mocha": "^11.7.5",
84
+ "nodemon": "^3.1.10",
85
+ "npm-upgrade": "^3.1.2",
90
86
  "ts-node": "^10.9.2",
91
- "typescript": "^5.6.3"
87
+ "typescript": "^5.9.3"
92
88
  },
93
89
  "repository": {
94
90
  "type": "git",
@@ -106,5 +102,7 @@
106
102
  "lib": "lib",
107
103
  "test": "test"
108
104
  },
109
- "packageManager": "yarn@4.1.0"
105
+ "engines": {
106
+ "node": ">=24"
107
+ }
110
108
  }
@@ -1,19 +1,9 @@
1
1
  import { FastifyReply, FastifyRequest } from 'fastify'
2
2
  import { AuthenticatedUser } from '../../../../types/global'
3
3
 
4
- export function currentUser(req: FastifyRequest, reply: FastifyReply) {
5
- const user: AuthenticatedUser | undefined = req.user
6
- reply.send(user ? { ...user, roles: req.roles() } : {})
7
- }
8
-
9
- export function isAdmin(req: FastifyRequest, reply: FastifyReply) {
10
- const user: AuthenticatedUser | undefined = req.user
11
- reply.send({ isAdmin: user?.getId() && req.hasRole(roles.admin) })
12
- }
13
-
14
- export function getRoles(req: FastifyRequest, reply: FastifyReply) {
4
+ export async function getRoles(req: FastifyRequest, reply: FastifyReply) {
15
5
  const allRoles = Object.keys(roles).map((key) => roles[key])
16
- reply.send(allRoles)
6
+ return reply.send(allRoles)
17
7
  }
18
8
 
19
9
  export async function count(req: FastifyRequest, reply: FastifyReply) {
@@ -32,13 +22,24 @@ export async function findOne(req: FastifyRequest, reply: FastifyReply) {
32
22
  }
33
23
 
34
24
  export async function create(req: FastifyRequest, reply: FastifyReply) {
25
+ if (!req.hasRole(roles.admin)) {
26
+ return reply.status(403).send(Error('Only admins can create users'))
27
+ }
28
+
35
29
  const { id, ...data } = req.data()
30
+
31
+ if (data.roles && data.roles.includes(roles.admin)) {
32
+ if (!config.enable || config.options?.allow_multiple_admin !== true) {
33
+ return reply.status(403).send(Error('Cannot assign admin role to a user'))
34
+ }
35
+ }
36
+
36
37
  const user = await req.server['userManager'].createUser(data)
37
38
  return user ? entity.User.save(user) : reply.status(400).send(Error('User not creatable'))
38
39
  }
39
40
 
40
41
  export async function update(req: FastifyRequest, reply: FastifyReply) {
41
- const { id, ...userData } = req.parameters()
42
+ const { id, ...userData } = req.data()
42
43
  if (!id) {
43
44
  return reply.status(400).send('Missing required id parameter')
44
45
  }
@@ -53,3 +54,24 @@ export async function remove(req: FastifyRequest, reply: FastifyReply) {
53
54
  }
54
55
  return await req.server['userManager'].deleteUser(id)
55
56
  }
57
+
58
+ export async function getCurrentUser(req: FastifyRequest, reply: FastifyReply) {
59
+ const user: AuthenticatedUser | undefined = req.user
60
+ return reply.send(user ? { ...user, roles: req.roles() } : {})
61
+ }
62
+
63
+ export async function updateCurrentUser(req: FastifyRequest, reply: FastifyReply) {
64
+ const user: AuthenticatedUser | undefined = req.user
65
+ const id = user?.getId()
66
+ if (!id) {
67
+ return reply.status(403).send('Cannot update current user')
68
+ }
69
+
70
+ const { id: _id, ...userData } = req.data()
71
+ return await req.server['userManager'].updateUserById(id, userData)
72
+ }
73
+
74
+ export async function isAdmin(req: FastifyRequest, reply: FastifyReply) {
75
+ const user: AuthenticatedUser | undefined = req.user
76
+ return reply.send({ isAdmin: user?.getId() && req.hasRole(roles.admin) })
77
+ }
@@ -64,9 +64,9 @@ module.exports = {
64
64
  {
65
65
  method: 'GET',
66
66
  path: '/:id',
67
- roles: [],
67
+ roles: [roles.admin],
68
68
  handler: 'user.findOne',
69
- middlewares: [],
69
+ middlewares: ['global.isAuthenticated'],
70
70
  config: {
71
71
  title: 'Find user',
72
72
  description: 'Get user by id',
@@ -82,9 +82,9 @@ module.exports = {
82
82
  {
83
83
  method: 'PUT',
84
84
  path: '/:id',
85
- roles: [],
85
+ roles: [roles.admin],
86
86
  handler: 'user.update',
87
- middlewares: [],
87
+ middlewares: ['global.isAuthenticated'],
88
88
  config: {
89
89
  title: 'Update user',
90
90
  description: 'Updates a user by id',
@@ -101,9 +101,9 @@ module.exports = {
101
101
  {
102
102
  method: 'POST',
103
103
  path: '/',
104
- roles: [],
104
+ roles: [roles.admin],
105
105
  handler: 'user.create',
106
- middlewares: [],
106
+ middlewares: ['global.isAuthenticated'],
107
107
  config: {
108
108
  title: 'Create a user',
109
109
  description: 'Creates a new user',
@@ -119,9 +119,9 @@ module.exports = {
119
119
  {
120
120
  method: 'DELETE',
121
121
  path: '/:id',
122
- roles: [],
122
+ roles: [roles.admin],
123
123
  handler: 'user.remove',
124
- middlewares: [],
124
+ middlewares: ['global.isAuthenticated'],
125
125
  config: {
126
126
  title: 'Delete user',
127
127
  description: 'Deletes user by id',
@@ -138,7 +138,7 @@ module.exports = {
138
138
  method: 'GET',
139
139
  path: '/me',
140
140
  roles: [],
141
- handler: 'user.currentUser',
141
+ handler: 'user.getCurrentUser',
142
142
  middlewares: ['global.isAuthenticated'],
143
143
  config: {
144
144
  title: 'Get current user',
@@ -148,6 +148,24 @@ module.exports = {
148
148
  }
149
149
  }
150
150
  },
151
+ {
152
+ method: 'PUT',
153
+ path: '/me',
154
+ roles: [],
155
+ handler: 'user.updateCurrentUser',
156
+ middlewares: ['global.isAuthenticated'],
157
+ config: {
158
+ title: 'Update current user',
159
+ description: 'Update current user',
160
+ body: { $ref: 'currentUserBodySchema#' },
161
+ response: {
162
+ 200: {
163
+ description: 'Default response',
164
+ $ref: 'userSchema#'
165
+ }
166
+ }
167
+ }
168
+ },
151
169
  {
152
170
  method: 'GET',
153
171
  path: '/is-admin',
@@ -4,6 +4,7 @@ module.exports = {
4
4
  name: 'general',
5
5
  enable: true,
6
6
  options: {
7
+ allow_multiple_admin: false,
7
8
  reset_external_id_on_login: false,
8
9
  scheduler: false,
9
10
  embedded_auth: true
@@ -7,6 +7,7 @@ export function load() {
7
7
  name: 'general',
8
8
  enable: true,
9
9
  options: {
10
+ allow_multiple_admin: false,
10
11
  reset_external_id_on_login: false,
11
12
  scheduler: false,
12
13
  embedded_auth: true
@@ -1,3 +1,12 @@
1
+ export const currentUserBodySchema = {
2
+ $id: 'currentUserBodySchema',
3
+ type: 'object',
4
+ nullable: true,
5
+ properties: {
6
+ username: { type: 'string' }
7
+ }
8
+ }
9
+
1
10
  export const userBodySchema = {
2
11
  $id: 'userBodySchema',
3
12
  type: 'object',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@volcanicminds/backend",
3
- "version": "1.0.4",
4
- "codename": "turin",
3
+ "version": "2.0.1",
4
+ "codename": "rome",
5
5
  "license": "MIT",
6
6
  "description": "The volcanic (minds) backend",
7
7
  "keywords": [
@@ -29,9 +29,6 @@
29
29
  ],
30
30
  "main": "dist/index",
31
31
  "typings": "dist/index",
32
- "engines": {
33
- "node": ">=16"
34
- },
35
32
  "scripts": {
36
33
  "clean": "rm -rf dist esm",
37
34
  "prebuild": "npm run clean",
@@ -44,51 +41,50 @@
44
41
  "server": "cd dist && node server.js",
45
42
  "start": "ts-node server.ts",
46
43
  "dev": "nodemon --exec \"ts-node\" server.ts",
47
- "test": "yarn test:full",
44
+ "test": "npm run test:full",
48
45
  "test:full": "cross-env PORT=2231 NODE_ENV=memory BROWSER=false mocha ./test/index.spec.ts -t 100000",
49
- "reset": "yarn && yarn up && yarn compile",
50
- "upgrade-deps": "yarn upgrade-interactive",
51
- "upgrade-pkg": "yarn npm-upgrade",
46
+ "reset": "npm install && npm update && npm run compile",
47
+ "upgrade-deps": "npx npm-check-updates -u",
52
48
  "combine": "node combine.js"
53
49
  },
54
50
  "dependencies": {
55
- "@apollo/server": "^4.11.0",
56
- "@as-integrations/fastify": "^2.1.1",
57
- "@fastify/compress": "^7.0.3",
58
- "@fastify/cors": "^9.0.1",
59
- "@fastify/helmet": "^11.1.1",
60
- "@fastify/jwt": "^8.0.1",
61
- "@fastify/multipart": "^8.3.0",
62
- "@fastify/rate-limit": "^9.1.0",
63
- "@fastify/schedule": "^4.1.1",
64
- "@fastify/swagger": "^8.15.0",
65
- "@fastify/swagger-ui": "^3.1.0",
66
- "@types/node": "^20.17.0",
67
- "dayjs": "^1.11.13",
68
- "dotenv": "^16.4.5",
69
- "fastify": "^4.28.1",
70
- "fastify-raw-body": "^4.3.0",
71
- "glob": "^10.4.5",
72
- "graphql": "^16.9.0",
73
- "i18n": "^0.15.1",
51
+ "@apollo/server": "^5.1.0",
52
+ "@as-integrations/fastify": "^3.1.0",
53
+ "@fastify/compress": "^8.1.0",
54
+ "@fastify/cors": "^11.1.0",
55
+ "@fastify/helmet": "^13.0.2",
56
+ "@fastify/jwt": "^10.0.0",
57
+ "@fastify/multipart": "^9.3.0",
58
+ "@fastify/rate-limit": "^10.3.0",
59
+ "@fastify/schedule": "^6.0.0",
60
+ "@fastify/swagger": "^9.5.2",
61
+ "@fastify/swagger-ui": "^5.2.3",
62
+ "@types/node": "^24.10.0",
63
+ "dayjs": "^1.11.19",
64
+ "dotenv": "^17.2.3",
65
+ "fastify": "^5.6.1",
66
+ "fastify-raw-body": "^5.0.0",
67
+ "glob": "^11.0.3",
68
+ "graphql": "^16.12.0",
69
+ "i18n": "^0.15.3",
74
70
  "lodash": "^4.17.21",
75
- "nanoid": "^5.0.7",
71
+ "nanoid": "^5.1.6",
76
72
  "object-sizeof": "^2.6.5",
77
- "pino": "^9.5.0",
78
- "pino-pretty": "^11.3.0",
73
+ "pino": "^10.1.0",
74
+ "pino-pretty": "^13.1.2",
79
75
  "root-require": "^0.3.1",
80
- "semver": "^7.6.3",
81
- "toad-scheduler": "^3.0.1"
76
+ "semver": "^7.7.3",
77
+ "toad-scheduler": "^3.1.0"
82
78
  },
83
79
  "devDependencies": {
84
- "@types/mocha": "^10.0.9",
85
- "cross-env": "^7.0.3",
86
- "expect": "^29.7.0",
87
- "mocha": "^10.7.3",
88
- "nodemon": "^3.1.7",
89
- "npm-upgrade": "^3.1.0",
80
+ "@types/mocha": "^10.0.10",
81
+ "cross-env": "^10.1.0",
82
+ "expect": "^30.2.0",
83
+ "mocha": "^11.7.5",
84
+ "nodemon": "^3.1.10",
85
+ "npm-upgrade": "^3.1.2",
90
86
  "ts-node": "^10.9.2",
91
- "typescript": "^5.6.3"
87
+ "typescript": "^5.9.3"
92
88
  },
93
89
  "repository": {
94
90
  "type": "git",
@@ -106,5 +102,7 @@
106
102
  "lib": "lib",
107
103
  "test": "test"
108
104
  },
109
- "packageManager": "yarn@4.1.0"
105
+ "engines": {
106
+ "node": ">=24"
107
+ }
110
108
  }
package/types/global.d.ts CHANGED
@@ -57,6 +57,7 @@ export interface GeneralConfig {
57
57
  name: string
58
58
  enable: boolean
59
59
  options: {
60
+ allow_multiple_admin: boolean
60
61
  reset_external_id_on_login: boolean
61
62
  scheduler: boolean
62
63
  embedded_auth: boolean