@budibase/worker 1.0.200-alpha.3 → 1.0.200

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 (40) hide show
  1. package/Dockerfile +0 -3
  2. package/nodemon.json +1 -1
  3. package/package.json +46 -56
  4. package/scripts/dev/manage.js +0 -2
  5. package/scripts/jestSetup.js +0 -9
  6. package/scripts/load/users.js +4 -4
  7. package/src/api/controllers/global/auth.ts +14 -21
  8. package/src/api/controllers/global/configs.js +2 -126
  9. package/src/api/controllers/global/roles.js +3 -3
  10. package/src/api/controllers/global/self.js +3 -12
  11. package/src/api/controllers/global/users.ts +88 -48
  12. package/src/api/routes/global/self.js +2 -2
  13. package/src/api/routes/global/users.js +3 -3
  14. package/src/api/routes/tests/auth.spec.js +16 -38
  15. package/src/api/routes/tests/configs.spec.js +7 -223
  16. package/src/api/routes/tests/email.spec.js +7 -8
  17. package/src/api/routes/tests/realEmail.spec.js +5 -5
  18. package/src/api/routes/tests/users.spec.js +13 -299
  19. package/src/{tests → api/routes/tests/utilities}/TestConfiguration.js +111 -68
  20. package/src/api/routes/tests/utilities/controllers.js +7 -0
  21. package/src/api/routes/tests/utilities/index.js +41 -0
  22. package/src/api/routes/tests/utilities/structures.js +2 -0
  23. package/src/api/utilities/index.js +33 -0
  24. package/src/api/{routes/validation/users.ts → utilities/validation.js} +4 -4
  25. package/src/index.ts +0 -2
  26. package/tsconfig.json +15 -21
  27. package/src/api/routes/tests/self.spec.js +0 -58
  28. package/src/api/routes/validation/index.ts +0 -1
  29. package/src/sdk/index.ts +0 -1
  30. package/src/sdk/users/events.ts +0 -161
  31. package/src/sdk/users/index.ts +0 -1
  32. package/src/sdk/users/users.ts +0 -201
  33. package/src/tests/controllers.js +0 -7
  34. package/src/tests/index.js +0 -12
  35. package/src/tests/mocks/email.js +0 -10
  36. package/src/tests/mocks/index.js +0 -5
  37. package/src/tests/structures/configs.js +0 -76
  38. package/src/tests/structures/index.js +0 -12
  39. package/src/tests/structures/users.ts +0 -28
  40. package/tsconfig.build.json +0 -25
@@ -1,8 +1,8 @@
1
- import joiValidator from "../../../middleware/joi-validator"
2
- import Joi from "joi"
1
+ const joiValidator = require("../../middleware/joi-validator")
2
+ const Joi = require("joi")
3
3
 
4
- export const buildUserSaveValidation = (isSelf = false) => {
5
- let schema: any = {
4
+ exports.buildUserSaveValidation = (isSelf = false) => {
5
+ let schema = {
6
6
  email: Joi.string().allow(null, ""),
7
7
  password: Joi.string().allow(null, ""),
8
8
  forceResetPassword: Joi.boolean().optional(),
package/src/index.ts CHANGED
@@ -18,7 +18,6 @@ const http = require("http")
18
18
  const api = require("./api")
19
19
  const redis = require("./utilities/redis")
20
20
  const Sentry = require("@sentry/node")
21
- import { events } from "@budibase/backend-core"
22
21
 
23
22
  // this will setup http and https proxies form env variables
24
23
  bootstrap()
@@ -74,7 +73,6 @@ server.on("close", async () => {
74
73
  console.log("Server Closed")
75
74
  }
76
75
  await redis.shutdown()
77
- await events.shutdown()
78
76
  if (!env.isTest()) {
79
77
  process.exit(errCode)
80
78
  }
package/tsconfig.json CHANGED
@@ -1,29 +1,23 @@
1
1
  {
2
- "extends": "./tsconfig.build.json",
3
2
  "compilerOptions": {
4
- "composite": true,
5
- "declaration": true,
6
- "sourceMap": true,
7
- "baseUrl": ".",
8
- "paths": {
9
- "@budibase/types": ["../types/src"],
10
- "@budibase/backend-core": ["../backend-core/src"],
11
- "@budibase/backend-core/*": ["../backend-core/*"]
12
- }
3
+ "target": "es6",
4
+ "module": "commonjs",
5
+ "lib": ["es2019"],
6
+ "allowJs": true,
7
+ "outDir": "dist",
8
+ "strict": true,
9
+ "noImplicitAny": true,
10
+ "esModuleInterop": true,
11
+ "resolveJsonModule": true,
12
+ "incremental": true
13
13
  },
14
- "ts-node": {
15
- "require": ["tsconfig-paths/register"]
16
- },
17
- "references": [
18
- { "path": "../types" },
19
- { "path": "../backend-core" },
20
- ],
21
14
  "include": [
22
- "src/**/*",
23
- "package.json"
15
+ "./src/**/*"
24
16
  ],
25
17
  "exclude": [
26
18
  "node_modules",
27
- "dist"
19
+ "**/*.json",
20
+ "**/*.spec.ts",
21
+ "**/*.spec.js"
28
22
  ]
29
- }
23
+ }
@@ -1,58 +0,0 @@
1
- jest.mock("nodemailer")
2
- const { config, request } = require("../../../tests")
3
- const { events } = require("@budibase/backend-core")
4
-
5
- describe("/api/global/self", () => {
6
-
7
- beforeAll(async () => {
8
- await config.beforeAll()
9
- })
10
-
11
- afterAll(async () => {
12
- await config.afterAll()
13
- })
14
-
15
- beforeEach(() => {
16
- jest.clearAllMocks()
17
- })
18
-
19
- const updateSelf = async (user) => {
20
- const res = await request
21
- .post(`/api/global/self`)
22
- .send(user)
23
- .set(config.defaultHeaders())
24
- .expect("Content-Type", /json/)
25
- .expect(200)
26
- return res
27
- }
28
-
29
- describe("update", () => {
30
-
31
- it("should update self", async () => {
32
- const user = await config.createUser()
33
-
34
- delete user.password
35
- const res = await updateSelf(user)
36
-
37
- expect(res.body._id).toBe(user._id)
38
- expect(events.user.updated).toBeCalledTimes(1)
39
- expect(events.user.updated).toBeCalledWith(user)
40
- expect(events.user.passwordUpdated).not.toBeCalled()
41
- })
42
-
43
- it("should update password", async () => {
44
- const user = await config.createUser()
45
- const password = "newPassword"
46
- user.password = password
47
-
48
- const res = await updateSelf(user)
49
-
50
- delete user.password
51
- expect(res.body._id).toBe(user._id)
52
- expect(events.user.updated).toBeCalledTimes(1)
53
- expect(events.user.updated).toBeCalledWith(user)
54
- expect(events.user.passwordUpdated).toBeCalledTimes(1)
55
- expect(events.user.passwordUpdated).toBeCalledWith(user)
56
- })
57
- })
58
- })
@@ -1 +0,0 @@
1
- export * as users from "./users"
package/src/sdk/index.ts DELETED
@@ -1 +0,0 @@
1
- export * as users from "./users"
@@ -1,161 +0,0 @@
1
- import env from "../../environment"
2
- import { events, accounts, tenancy } from "@budibase/backend-core"
3
- import { User, UserRoles, CloudAccount } from "@budibase/types"
4
-
5
- export const handleDeleteEvents = async (user: any) => {
6
- await events.user.deleted(user)
7
-
8
- if (isBuilder(user)) {
9
- await events.user.permissionBuilderRemoved(user)
10
- }
11
-
12
- if (isAdmin(user)) {
13
- await events.user.permissionAdminRemoved(user)
14
- }
15
- }
16
-
17
- const assignAppRoleEvents = async (
18
- user: User,
19
- roles: UserRoles,
20
- existingRoles: UserRoles
21
- ) => {
22
- for (const [appId, role] of Object.entries(roles)) {
23
- // app role in existing is not same as new
24
- if (!existingRoles || existingRoles[appId] !== role) {
25
- await events.role.assigned(user, role)
26
- }
27
- }
28
- }
29
-
30
- const unassignAppRoleEvents = async (
31
- user: User,
32
- roles: UserRoles,
33
- existingRoles: UserRoles
34
- ) => {
35
- if (!existingRoles) {
36
- return
37
- }
38
- for (const [appId, role] of Object.entries(existingRoles)) {
39
- // app role in new is not same as existing
40
- if (!roles || roles[appId] !== role) {
41
- await events.role.unassigned(user, role)
42
- }
43
- }
44
- }
45
-
46
- const handleAppRoleEvents = async (user: any, existingUser: any) => {
47
- const roles = user.roles
48
- const existingRoles = existingUser?.roles
49
-
50
- await assignAppRoleEvents(user, roles, existingRoles)
51
- await unassignAppRoleEvents(user, roles, existingRoles)
52
- }
53
-
54
- export const handleSaveEvents = async (user: any, existingUser: any) => {
55
- const tenantId = tenancy.getTenantId()
56
- let tenantAccount: CloudAccount | undefined
57
- if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
58
- tenantAccount = await accounts.getAccountByTenantId(tenantId)
59
- }
60
- await events.identification.identifyUser(user, tenantAccount)
61
-
62
- if (existingUser) {
63
- await events.user.updated(user)
64
-
65
- if (isRemovingBuilder(user, existingUser)) {
66
- await events.user.permissionBuilderRemoved(user)
67
- }
68
-
69
- if (isRemovingAdmin(user, existingUser)) {
70
- await events.user.permissionAdminRemoved(user)
71
- }
72
-
73
- if (
74
- !existingUser.forceResetPassword &&
75
- user.forceResetPassword &&
76
- user.password
77
- ) {
78
- await events.user.passwordForceReset(user)
79
- }
80
- } else {
81
- await events.user.created(user)
82
- }
83
-
84
- if (isAddingBuilder(user, existingUser)) {
85
- await events.user.permissionBuilderAssigned(user)
86
- }
87
-
88
- if (isAddingAdmin(user, existingUser)) {
89
- await events.user.permissionAdminAssigned(user)
90
- }
91
-
92
- await handleAppRoleEvents(user, existingUser)
93
- }
94
-
95
- const isBuilder = (user: any) => user.builder && user.builder.global
96
- const isAdmin = (user: any) => user.admin && user.admin.global
97
-
98
- export const isAddingBuilder = (user: any, existingUser: any) => {
99
- return isAddingPermission(user, existingUser, isBuilder)
100
- }
101
-
102
- export const isRemovingBuilder = (user: any, existingUser: any) => {
103
- return isRemovingPermission(user, existingUser, isBuilder)
104
- }
105
-
106
- const isAddingAdmin = (user: any, existingUser: any) => {
107
- return isAddingPermission(user, existingUser, isAdmin)
108
- }
109
-
110
- const isRemovingAdmin = (user: any, existingUser: any) => {
111
- return isRemovingPermission(user, existingUser, isAdmin)
112
- }
113
-
114
- /**
115
- * Check if a permission is being added to a new or existing user.
116
- */
117
- const isAddingPermission = (
118
- user: any,
119
- existingUser: any,
120
- hasPermission: any
121
- ) => {
122
- // new user doesn't have the permission
123
- if (!hasPermission(user)) {
124
- return false
125
- }
126
-
127
- // existing user has the permission
128
- if (existingUser && hasPermission(existingUser)) {
129
- return false
130
- }
131
-
132
- // permission is being added
133
- return true
134
- }
135
-
136
- /**
137
- * Check if a permission is being removed from an existing user.
138
- */
139
- const isRemovingPermission = (
140
- user: any,
141
- existingUser: any,
142
- hasPermission: any
143
- ) => {
144
- // new user has the permission
145
- if (hasPermission(user)) {
146
- return false
147
- }
148
-
149
- // no existing user or existing user doesn't have the permission
150
- if (!existingUser) {
151
- return false
152
- }
153
-
154
- // existing user doesn't have the permission
155
- if (!hasPermission(existingUser)) {
156
- return false
157
- }
158
-
159
- // permission is being removed
160
- return true
161
- }
@@ -1 +0,0 @@
1
- export * from "./users"
@@ -1,201 +0,0 @@
1
- import env from "../../environment"
2
- import { quotas } from "@budibase/pro"
3
- import * as apps from "../../utilities/appService"
4
- import * as eventHelpers from "./events"
5
- import {
6
- tenancy,
7
- utils,
8
- db as dbUtils,
9
- constants,
10
- cache,
11
- users as usersCore,
12
- deprovisioning,
13
- sessions,
14
- HTTPError,
15
- accounts,
16
- migrations,
17
- } from "@budibase/backend-core"
18
- import { MigrationType } from "@budibase/types"
19
-
20
- /**
21
- * Retrieves all users from the current tenancy.
22
- */
23
- export const allUsers = async () => {
24
- const db = tenancy.getGlobalDB()
25
- const response = await db.allDocs(
26
- dbUtils.getGlobalUserParams(null, {
27
- include_docs: true,
28
- })
29
- )
30
- return response.rows.map((row: any) => row.doc)
31
- }
32
-
33
- /**
34
- * Gets a user by ID from the global database, based on the current tenancy.
35
- */
36
- export const getUser = async (userId: string) => {
37
- const db = tenancy.getGlobalDB()
38
- let user
39
- try {
40
- user = await db.get(userId)
41
- } catch (err: any) {
42
- // no user found, just return nothing
43
- if (err.status === 404) {
44
- return {}
45
- }
46
- throw err
47
- }
48
- if (user) {
49
- delete user.password
50
- }
51
- return user
52
- }
53
-
54
- interface SaveUserOpts {
55
- hashPassword?: boolean
56
- requirePassword?: boolean
57
- bulkCreate?: boolean
58
- }
59
-
60
- export const save = async (
61
- user: any,
62
- opts: SaveUserOpts = {
63
- hashPassword: true,
64
- requirePassword: true,
65
- bulkCreate: false,
66
- }
67
- ) => {
68
- const tenantId = tenancy.getTenantId()
69
- const db = tenancy.getGlobalDB()
70
- let { email, password, _id } = user
71
- // make sure another user isn't using the same email
72
- let dbUser: any
73
- if (opts.bulkCreate) {
74
- dbUser = null
75
- } else if (email) {
76
- // check budibase users inside the tenant
77
- dbUser = await usersCore.getGlobalUserByEmail(email)
78
- if (dbUser != null && (dbUser._id !== _id || Array.isArray(dbUser))) {
79
- throw `Email address ${email} already in use.`
80
- }
81
-
82
- // check budibase users in other tenants
83
- if (env.MULTI_TENANCY) {
84
- const tenantUser = await tenancy.getTenantUser(email)
85
- if (tenantUser != null && tenantUser.tenantId !== tenantId) {
86
- throw `Email address ${email} already in use.`
87
- }
88
- }
89
-
90
- // check root account users in account portal
91
- if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
92
- const account = await accounts.getAccount(email)
93
- if (account && account.verified && account.tenantId !== tenantId) {
94
- throw `Email address ${email} already in use.`
95
- }
96
- }
97
- } else if (_id) {
98
- dbUser = await db.get(_id)
99
- }
100
-
101
- // get the password, make sure one is defined
102
- let hashedPassword
103
- if (password) {
104
- hashedPassword = opts.hashPassword ? await utils.hash(password) : password
105
- } else if (dbUser) {
106
- hashedPassword = dbUser.password
107
- } else if (opts.requirePassword) {
108
- throw "Password must be specified."
109
- }
110
-
111
- _id = _id || dbUtils.generateGlobalUserID()
112
- user = {
113
- createdAt: Date.now(),
114
- ...dbUser,
115
- ...user,
116
- _id,
117
- password: hashedPassword,
118
- tenantId,
119
- }
120
- // make sure the roles object is always present
121
- if (!user.roles) {
122
- user.roles = {}
123
- }
124
- // add the active status to a user if its not provided
125
- if (user.status == null) {
126
- user.status = constants.UserStatus.ACTIVE
127
- }
128
- try {
129
- const putOpts = {
130
- password: hashedPassword,
131
- ...user,
132
- }
133
- if (opts.bulkCreate) {
134
- return putOpts
135
- }
136
- // save the user to db
137
- let response
138
- const putUserFn = () => {
139
- return db.put(user)
140
- }
141
- if (eventHelpers.isAddingBuilder(user, dbUser)) {
142
- response = await quotas.addDeveloper(putUserFn)
143
- } else {
144
- response = await putUserFn()
145
- }
146
- user._rev = response.rev
147
-
148
- await eventHelpers.handleSaveEvents(user, dbUser)
149
-
150
- if (env.MULTI_TENANCY) {
151
- const afterCreateTenant = () =>
152
- migrations.backPopulateMigrations({
153
- type: MigrationType.GLOBAL,
154
- tenantId,
155
- })
156
- await tenancy.tryAddTenant(tenantId, _id, email, afterCreateTenant)
157
- }
158
- await cache.user.invalidateUser(response.id)
159
- // let server know to sync user
160
- await apps.syncUserInApps(user._id)
161
-
162
- return {
163
- _id: response.id,
164
- _rev: response.rev,
165
- email,
166
- }
167
- } catch (err: any) {
168
- if (err.status === 409) {
169
- throw "User exists already"
170
- } else {
171
- throw err
172
- }
173
- }
174
- }
175
-
176
- export const destroy = async (id: string, currentUser: any) => {
177
- const db = tenancy.getGlobalDB()
178
- const dbUser = await db.get(id)
179
-
180
- if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
181
- // root account holder can't be deleted from inside budibase
182
- const email = dbUser.email
183
- const account = await accounts.getAccount(email)
184
- if (account) {
185
- if (email === currentUser.email) {
186
- throw new HTTPError('Please visit "Account" to delete this user', 400)
187
- } else {
188
- throw new HTTPError("Account holder cannot be deleted", 400)
189
- }
190
- }
191
- }
192
-
193
- await deprovisioning.removeUserFromInfoDB(dbUser)
194
- await db.remove(dbUser._id, dbUser._rev)
195
- await eventHelpers.handleDeleteEvents(dbUser)
196
- await quotas.removeUser(dbUser)
197
- await cache.user.invalidateUser(dbUser._id)
198
- await sessions.invalidateSessions(dbUser._id)
199
- // let server know to sync user
200
- await apps.syncUserInApps(dbUser._id)
201
- }
@@ -1,7 +0,0 @@
1
- module.exports = {
2
- email: require("../api/controllers/global/email"),
3
- workspaces: require("../api/controllers/global/workspaces"),
4
- config: require("../api/controllers/global/configs"),
5
- templates: require("../api/controllers/global/templates"),
6
- users: require("../api/controllers/global/users"),
7
- }
@@ -1,12 +0,0 @@
1
- const TestConfiguration = require("./TestConfiguration")
2
- const structures = require("./structures")
3
- const mocks = require("./mocks")
4
- const config = new TestConfiguration()
5
- const request = config.getRequest()
6
-
7
- module.exports = {
8
- structures,
9
- mocks,
10
- config,
11
- request,
12
- }
@@ -1,10 +0,0 @@
1
- exports.mock = () => {
2
- // mock the email system
3
- const sendMailMock = jest.fn()
4
- const nodemailer = require("nodemailer")
5
- nodemailer.createTransport.mockReturnValue({
6
- sendMail: sendMailMock,
7
- verify: jest.fn(),
8
- })
9
- return sendMailMock
10
- }
@@ -1,5 +0,0 @@
1
- const email = require("./email")
2
-
3
- module.exports = {
4
- email,
5
- }
@@ -1,76 +0,0 @@
1
- const { Configs } = require("../../constants")
2
- const { utils } = require("@budibase/backend-core")
3
-
4
- exports.oidc = conf => {
5
- return {
6
- type: Configs.OIDC,
7
- config: {
8
- configs: [
9
- {
10
- configUrl: "http://someconfigurl",
11
- clientID: "clientId",
12
- clientSecret: "clientSecret",
13
- logo: "Microsoft",
14
- name: "Active Directory",
15
- uuid: utils.newid(),
16
- activated: true,
17
- ...conf,
18
- },
19
- ],
20
- },
21
- }
22
- }
23
-
24
- exports.google = conf => {
25
- return {
26
- type: Configs.GOOGLE,
27
- config: {
28
- clientID: "clientId",
29
- clientSecret: "clientSecret",
30
- activated: true,
31
- ...conf,
32
- },
33
- }
34
- }
35
-
36
- exports.smtp = conf => {
37
- return {
38
- type: Configs.SMTP,
39
- config: {
40
- port: 12345,
41
- host: "smtptesthost.com",
42
- from: "testfrom@test.com",
43
- subject: "Hello!",
44
- secure: false,
45
- ...conf,
46
- },
47
- }
48
- }
49
-
50
- exports.smtpEthereal = () => {
51
- return {
52
- type: Configs.SMTP,
53
- config: {
54
- port: 587,
55
- host: "smtp.ethereal.email",
56
- secure: false,
57
- auth: {
58
- user: "don.bahringer@ethereal.email",
59
- pass: "yCKSH8rWyUPbnhGYk9",
60
- },
61
- connectionTimeout: 1000, // must be less than the jest default of 5000
62
- },
63
- }
64
- }
65
-
66
- exports.settings = conf => {
67
- return {
68
- type: Configs.SETTINGS,
69
- config: {
70
- platformUrl: "http://localhost:10000",
71
- logoUrl: "",
72
- company: "Budibase",
73
- ...conf,
74
- },
75
- }
76
- }
@@ -1,12 +0,0 @@
1
- const configs = require("./configs")
2
- const users = require("./users")
3
-
4
- const TENANT_ID = "default"
5
- const CSRF_TOKEN = "e3727778-7af0-4226-b5eb-f43cbe60a306"
6
-
7
- module.exports = {
8
- configs,
9
- users,
10
- TENANT_ID,
11
- CSRF_TOKEN,
12
- }
@@ -1,28 +0,0 @@
1
- export const email = "test@test.com"
2
-
3
- export const user = (userProps: any) => {
4
- return {
5
- email: "test@test.com",
6
- password: "test",
7
- roles: {},
8
- ...userProps,
9
- }
10
- }
11
-
12
- export const adminUser = (userProps: any) => {
13
- return {
14
- ...user(userProps),
15
- admin: {
16
- global: true,
17
- },
18
- }
19
- }
20
-
21
- export const builderUser = (userProps: any) => {
22
- return {
23
- ...user(userProps),
24
- builder: {
25
- global: true,
26
- },
27
- }
28
- }
@@ -1,25 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es6",
4
- "module": "commonjs",
5
- "lib": ["es2020"],
6
- "allowJs": true,
7
- "strict": true,
8
- "noImplicitAny": true,
9
- "esModuleInterop": true,
10
- "resolveJsonModule": true,
11
- "incremental": true,
12
- "types": [ "node", "jest" ],
13
- "outDir": "dist",
14
- "skipLibCheck": true
15
- },
16
- "include": [
17
- "src/**/*"
18
- ],
19
- "exclude": [
20
- "node_modules",
21
- "dist",
22
- "**/*.spec.ts",
23
- "**/*.spec.js"
24
- ]
25
- }