This commit is contained in:
mike12345567 2023-01-06 16:46:50 +00:00
parent 1e046b9d7f
commit 60371d828e
9 changed files with 902 additions and 822 deletions

View File

@ -45,7 +45,7 @@
"dev:server": "yarn run kill-server && lerna run --parallel dev:builder --concurrency 1 --scope @budibase/backend-core --scope @budibase/worker --scope @budibase/server", "dev:server": "yarn run kill-server && lerna run --parallel dev:builder --concurrency 1 --scope @budibase/backend-core --scope @budibase/worker --scope @budibase/server",
"test": "lerna run test && yarn test:pro", "test": "lerna run test && yarn test:pro",
"test:pro": "bash scripts/pro/test.sh", "test:pro": "bash scripts/pro/test.sh",
"lint:eslint": "eslint packages", "lint:eslint": "eslint packages && eslint qa-core",
"lint:prettier": "prettier --check \"packages/**/*.{js,ts,svelte}\"", "lint:prettier": "prettier --check \"packages/**/*.{js,ts,svelte}\"",
"lint": "yarn run lint:eslint && yarn run lint:prettier", "lint": "yarn run lint:eslint && yarn run lint:prettier",
"lint:fix:eslint": "eslint --fix packages qa-core", "lint:fix:eslint": "eslint --fix packages qa-core",

View File

@ -4,130 +4,128 @@ import InternalAPIClient from "./InternalAPIClient"
import { responseMessage } from "../fixtures/types/responseMessage" import { responseMessage } from "../fixtures/types/responseMessage"
export default class UserManagementApi { export default class UserManagementApi {
api: InternalAPIClient api: InternalAPIClient
constructor(apiClient: InternalAPIClient) { constructor(apiClient: InternalAPIClient) {
this.api = apiClient this.api = apiClient
} }
async search(): Promise<[Response, Partial<User>[]]> { async search(): Promise<[Response, Partial<User>[]]> {
const response = await this.api.post(`/global/users/search`, {}) const response = await this.api.post(`/global/users/search`, {})
const json = await response.json() const json = await response.json()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(json.data.length).toBeGreaterThan(0) expect(json.data.length).toBeGreaterThan(0)
return [response, json] return [response, json]
} }
async getSelf(): Promise<[Response, Partial<User>]> { async getSelf(): Promise<[Response, Partial<User>]> {
const response = await this.api.get(`/global/self`) const response = await this.api.get(`/global/self`)
const json = await response.json() const json = await response.json()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
return [response, json] return [response, json]
} }
async getAll(): Promise<[Response, Partial<User>[]]> { async getAll(): Promise<[Response, Partial<User>[]]> {
const response = await this.api.get(`/global/users`) const response = await this.api.get(`/global/users`)
const json = await response.json() const json = await response.json()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(json.length).toBeGreaterThan(0) expect(json.length).toBeGreaterThan(0)
return [response, json] return [response, json]
} }
// This endpoint is used for one or more users when we want add users with passwords set. // This endpoint is used for one or more users when we want add users with passwords set.
async addMultiple(userList: Partial<User>[]): Promise<[Response, any]> { async addMultiple(userList: Partial<User>[]): Promise<[Response, any]> {
const body = { const body = {
create: { create: {
users: userList, users: userList,
groups: [] groups: [],
} },
}
const response = await this.api.post(`/global/users/bulk`, { body })
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.created.unsuccessful.length).toEqual(0)
expect(json.created.successful.length).toEqual(body.create.users.length)
return [response, json]
} }
const response = await this.api.post(`/global/users/bulk`, { body })
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.created.unsuccessful.length).toEqual(0)
expect(json.created.successful.length).toEqual(body.create.users.length)
return [response, json]
}
async deleteMultiple(userId: string[]): Promise<[Response, responseMessage]> { async deleteMultiple(userId: string[]): Promise<[Response, responseMessage]> {
const body = { const body = {
delete: { delete: {
userIds: [ userIds: [userId],
userId },
]
}
}
const response = await this.api.post(`/global/users/bulk`, { body })
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.deleted.successful.length).toEqual(1)
expect(json.deleted.unsuccessful.length).toEqual(0)
expect(json.deleted.successful[0].userId).toEqual(userId)
return [response, json]
}
async delete(userId: string): Promise<[Response, UserDeletedEvent]> {
const response = await this.api.del(`/global/users/${userId}`)
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.message).toEqual(`User ${userId} deleted.`)
return [response, json]
} }
const response = await this.api.post(`/global/users/bulk`, { body })
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.deleted.successful.length).toEqual(1)
expect(json.deleted.unsuccessful.length).toEqual(0)
expect(json.deleted.successful[0].userId).toEqual(userId)
return [response, json]
}
async delete(userId: string): Promise<[Response, UserDeletedEvent]> {
const response = await this.api.del(`/global/users/${userId}`)
const json = await response.json()
expect(response).toHaveStatusCode(200)
expect(json.message).toEqual(`User ${userId} deleted.`)
return [response, json]
}
async invite(body: any): Promise<[Response, responseMessage]> { async invite(body: any): Promise<[Response, responseMessage]> {
const response = await this.api.post(`/global/users/multi/invite`, { body }) const response = await this.api.post(`/global/users/multi/invite`, { body })
const json = await response.json() const json = await response.json()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(json.unsuccessful.length).toEqual(0) expect(json.unsuccessful.length).toEqual(0)
expect(json.successful.length).toEqual(body.length) expect(json.successful.length).toEqual(body.length)
return [response, json] return [response, json]
} }
async getRoles(): Promise<[Response, Role[]]> { async getRoles(): Promise<[Response, Role[]]> {
const response = await this.api.get(`/roles`) const response = await this.api.get(`/roles`)
const json = await response.json() const json = await response.json()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
return [response, json] return [response, json]
} }
async updateInfo(body: any): Promise<[Response, User]> { async updateInfo(body: any): Promise<[Response, User]> {
const response = await this.api.post(`/global/users/`, { body }) const response = await this.api.post(`/global/users/`, { body })
const json = await response.json() const json = await response.json()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(json._id).toEqual(body._id) expect(json._id).toEqual(body._id)
expect(json._rev).not.toEqual(body._rev) expect(json._rev).not.toEqual(body._rev)
return [response, json] return [response, json]
} }
async forcePasswordReset(body: any): Promise<[Response, User]> { async forcePasswordReset(body: any): Promise<[Response, User]> {
const response = await this.api.post(`/global/users/`, { body }) const response = await this.api.post(`/global/users/`, { body })
const json = await response.json() const json = await response.json()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(json._id).toEqual(body._id) expect(json._id).toEqual(body._id)
expect(json._rev).not.toEqual(body._rev) expect(json._rev).not.toEqual(body._rev)
return [response, json] return [response, json]
} }
async getInfo(userId: string): Promise<[Response, User]> { async getInfo(userId: string): Promise<[Response, User]> {
const response = await this.api.get(`/global/users/${userId}`) const response = await this.api.get(`/global/users/${userId}`)
const json = await response.json() const json = await response.json()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
return [response, json] return [response, json]
} }
async changeSelfPassword(body: Partial<User>): Promise<[Response, User]> { async changeSelfPassword(body: Partial<User>): Promise<[Response, User]> {
const response = await this.api.post(`/global/self`, { body }) const response = await this.api.post(`/global/self`, { body })
const json = await response.json() const json = await response.json()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(json._id).toEqual(body._id) expect(json._id).toEqual(body._id)
expect(json._rev).not.toEqual(body._rev) expect(json._rev).not.toEqual(body._rev)
return [response, json] return [response, json]
} }
async createRole(body: Partial<UserRoles>): Promise<[Response, UserRoles]> { async createRole(body: Partial<UserRoles>): Promise<[Response, UserRoles]> {
const response = await this.api.post(`/roles`, { body }) const response = await this.api.post(`/roles`, { body })
const json = await response.json() const json = await response.json()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
return [response, json] return [response, json]
} }
} }

View File

@ -13,13 +13,12 @@ export const generateApp = (
// Applications type doesn't work here, save to add useTemplate parameter? // Applications type doesn't work here, save to add useTemplate parameter?
export const appFromTemplate = (): any => { export const appFromTemplate = (): any => {
return ({ return {
name: generator.word(), name: generator.word(),
url: `/${generator.word()}`, url: `/${generator.word()}`,
useTemplate: "true", useTemplate: "true",
templateName: "Near Miss Register", templateName: "Near Miss Register",
templateKey: "app/near-miss-register", templateKey: "app/near-miss-register",
templateFile: undefined, templateFile: undefined,
}) }
} }

View File

@ -1,80 +1,82 @@
import generator from "../../generator"; import generator from "../../generator"
import { User } from "@budibase/types"; import { User } from "@budibase/types"
const generateDeveloper = (): Partial<User> => { const generateDeveloper = (): Partial<User> => {
const randomId = generator.guid(); const randomId = generator.guid()
return ({ return {
email: `pedro+${randomId}@budibase.com`, email: `pedro+${randomId}@budibase.com`,
password: randomId, password: randomId,
roles: {}, roles: {},
forceResetPassword: true, forceResetPassword: true,
builder: { builder: {
global: true global: true,
} },
}) }
} }
const generateAdmin = (): Partial<User> => { const generateAdmin = (): Partial<User> => {
const randomId = generator.guid(); const randomId = generator.guid()
return ({ return {
email: `pedro+${randomId}@budibase.com`, email: `pedro+${randomId}@budibase.com`,
password: randomId, password: randomId,
roles: {}, roles: {},
forceResetPassword: true, forceResetPassword: true,
admin: { admin: {
global: true global: true,
}, },
builder: { builder: {
global: true global: true,
} },
}) }
} }
const generateAppUser = (): Partial<User> => { const generateAppUser = (): Partial<User> => {
const randomId = generator.guid(); const randomId = generator.guid()
return ({ return {
email: `pedro+${randomId}@budibase.com`, email: `pedro+${randomId}@budibase.com`,
password: randomId, password: randomId,
roles: {}, roles: {},
forceResetPassword: true, forceResetPassword: true,
admin: { admin: {
global: false global: false,
}, },
builder: { builder: {
global: false global: false,
} },
}) }
} }
export const generateInviteUser = (): Object[] => { export const generateInviteUser = (): Object[] => {
const randomId = generator.guid(); const randomId = generator.guid()
return [{ return [
email: `pedro+${randomId}@budibase.com`, {
userInfo: { email: `pedro+${randomId}@budibase.com`,
userGroups: [] userInfo: {
} userGroups: [],
}] },
},
]
} }
export const generateUser = (amount: number = 1, role?: string): Partial<User>[] => { export const generateUser = (
const userList: Partial<User>[] = []; amount: number = 1,
for (let i = 0; i < amount; i++) { role?: string
switch (role) { ): Partial<User>[] => {
case "admin": const userList: Partial<User>[] = []
userList.push(generateAdmin()); for (let i = 0; i < amount; i++) {
break; switch (role) {
case "developer": case "admin":
userList.push(generateDeveloper()); userList.push(generateAdmin())
break; break
case "appUser": case "developer":
userList.push(generateAppUser()); userList.push(generateDeveloper())
break; break
default: case "appUser":
userList.push(generateAppUser()); userList.push(generateAppUser())
break; break
} default:
userList.push(generateAppUser())
break
} }
return userList }
return userList
} }

View File

@ -2,7 +2,10 @@ import TestConfiguration from "../../../config/internal-api/TestConfiguration"
import { Application } from "@budibase/server/api/controllers/public/mapping/types" import { Application } from "@budibase/server/api/controllers/public/mapping/types"
import { db } from "@budibase/backend-core" import { db } from "@budibase/backend-core"
import InternalAPIClient from "../../../config/internal-api/TestConfiguration/InternalAPIClient" import InternalAPIClient from "../../../config/internal-api/TestConfiguration/InternalAPIClient"
import { generateApp, appFromTemplate } from "../../../config/internal-api/fixtures/applications" import {
generateApp,
appFromTemplate,
} from "../../../config/internal-api/fixtures/applications"
import generator from "../../../config/generator" import generator from "../../../config/generator"
import generateScreen from "../../../config/internal-api/fixtures/screens" import generateScreen from "../../../config/internal-api/fixtures/screens"
@ -18,7 +21,6 @@ describe("Internal API - Application creation, update, publish and delete", () =
await config.afterAll() await config.afterAll()
}) })
it("Get applications without applications", async () => { it("Get applications without applications", async () => {
await config.applications.fetchEmptyAppList() await config.applications.fetchEmptyAppList()
}) })

View File

@ -1,7 +1,10 @@
import TestConfiguration from "../../../config/internal-api/TestConfiguration" import TestConfiguration from "../../../config/internal-api/TestConfiguration"
import { App } from "@budibase/types" import { App } from "@budibase/types"
import InternalAPIClient from "../../../config/internal-api/TestConfiguration/InternalAPIClient" import InternalAPIClient from "../../../config/internal-api/TestConfiguration/InternalAPIClient"
import { generateApp, appFromTemplate } from "../../../config/internal-api/fixtures/applications" import {
generateApp,
appFromTemplate,
} from "../../../config/internal-api/fixtures/applications"
import { Screen } from "@budibase/types" import { Screen } from "@budibase/types"
import generateScreen from "../../../config/internal-api/fixtures/screens" import generateScreen from "../../../config/internal-api/fixtures/screens"

View File

@ -5,86 +5,84 @@ import { generateUser } from "../../../config/internal-api/fixtures/userManageme
import { User } from "@budibase/types" import { User } from "@budibase/types"
describe("Internal API - User Management & Permissions", () => { describe("Internal API - User Management & Permissions", () => {
const api = new InternalAPIClient() const api = new InternalAPIClient()
const config = new TestConfiguration<Application>(api) const config = new TestConfiguration<Application>(api)
// Before each test, login as admin. Some tests will require login as a different user // Before each test, login as admin. Some tests will require login as a different user
beforeEach(async () => { beforeEach(async () => {
await config.loginAsAdmin() await config.loginAsAdmin()
}) })
afterAll(async () => { afterAll(async () => {
await config.afterAll() await config.afterAll()
}) })
it("Add Users with different roles", async () => { it("Add Users with different roles", async () => {
await config.users.search() await config.users.search()
await config.users.getRoles() await config.users.getRoles()
const admin = generateUser(1, "admin") const admin = generateUser(1, "admin")
expect(admin[0].builder?.global).toEqual(true) expect(admin[0].builder?.global).toEqual(true)
expect(admin[0].admin?.global).toEqual(true) expect(admin[0].admin?.global).toEqual(true)
const developer = generateUser(1, "developer") const developer = generateUser(1, "developer")
expect(developer[0].builder?.global).toEqual(true) expect(developer[0].builder?.global).toEqual(true)
const appUser = generateUser(1, "appUser") const appUser = generateUser(1, "appUser")
expect(appUser[0].builder?.global).toEqual(false) expect(appUser[0].builder?.global).toEqual(false)
expect(appUser[0].admin?.global).toEqual(false) expect(appUser[0].admin?.global).toEqual(false)
const userList = [...admin, ...developer, ...appUser] const userList = [...admin, ...developer, ...appUser]
await config.users.addMultiple(userList) await config.users.addMultiple(userList)
const [allUsersResponse, allUsersJson] = await config.users.getAll() const [allUsersResponse, allUsersJson] = await config.users.getAll()
expect(allUsersJson.length).toBeGreaterThan(0) expect(allUsersJson.length).toBeGreaterThan(0)
})
it("Delete User", async () => {
const appUser = generateUser()
expect(appUser[0].builder?.global).toEqual(false)
expect(appUser[0].admin?.global).toEqual(false)
const [userResponse, userJson] = await config.users.addMultiple(appUser)
const userId = userJson.created.successful[0]._id
await config.users.delete(<string>userId)
})
it("Reset Password", async () => {
const appUser = generateUser()
expect(appUser[0].builder?.global).toEqual(false)
expect(appUser[0].admin?.global).toEqual(false)
const [userResponse, userJson] = await config.users.addMultiple(appUser)
const [userInfoResponse, userInfoJson] = await config.users.getInfo(
userJson.created.successful[0]._id
)
const body: User = {
...userInfoJson,
password: "newPassword",
}
await config.users.forcePasswordReset(body)
})
}) it("Change User information", async () => {
const appUser = generateUser()
it("Delete User", async () => { expect(appUser[0].builder?.global).toEqual(false)
const appUser = generateUser() expect(appUser[0].admin?.global).toEqual(false)
expect(appUser[0].builder?.global).toEqual(false) const [userResponse, userJson] = await config.users.addMultiple(appUser)
expect(appUser[0].admin?.global).toEqual(false) const [userInfoResponse, userInfoJson] = await config.users.getInfo(
const [userResponse, userJson] = await config.users.addMultiple(appUser) userJson.created.successful[0]._id
const userId = userJson.created.successful[0]._id )
await config.users.delete(<string>userId) const body: User = {
}) ...userInfoJson,
firstName: "newFirstName",
it("Reset Password", async () => { lastName: "newLastName",
const appUser = generateUser() builder: {
expect(appUser[0].builder?.global).toEqual(false) global: true,
expect(appUser[0].admin?.global).toEqual(false) },
const [userResponse, userJson] = await config.users.addMultiple(appUser) }
const [userInfoResponse, userInfoJson] = await config.users.getInfo(userJson.created.successful[0]._id) await config.users.updateInfo(body)
const body: User = {
...userInfoJson,
password: "newPassword"
}
await config.users.forcePasswordReset(body)
})
it("Change User information", async () => {
const appUser = generateUser()
expect(appUser[0].builder?.global).toEqual(false)
expect(appUser[0].admin?.global).toEqual(false)
const [userResponse, userJson] = await config.users.addMultiple(appUser)
const [userInfoResponse, userInfoJson] = await config.users.getInfo(userJson.created.successful[0]._id)
const body: User = {
...userInfoJson,
firstName: "newFirstName",
lastName: "newLastName",
builder: {
global: true
}
}
await config.users.updateInfo(body)
const [changedUserInfoResponse, changedUserInfoJson] = await config.users.getInfo(userJson.created.successful[0]._id)
expect(changedUserInfoJson.builder?.global).toBeDefined()
expect(changedUserInfoJson.builder?.global).toEqual(true)
})
const [changedUserInfoResponse, changedUserInfoJson] =
await config.users.getInfo(userJson.created.successful[0]._id)
expect(changedUserInfoJson.builder?.global).toBeDefined()
expect(changedUserInfoJson.builder?.global).toEqual(true)
})
}) })

View File

@ -73,15 +73,15 @@ describe("Public API - /applications endpoints", () => {
}) })
it("POST - unpublish an unpublished application", async () => { it("POST - unpublish an unpublished application", async () => {
const [response] = await config.applications.unpublish( const [response] = await config.applications.unpublish(config.context._id)
config.context._id
)
expect(response).toHaveStatusCode(400) expect(response).toHaveStatusCode(400)
}) })
it("DELETE - delete a published application and the dev application", async () => { it("DELETE - delete a published application and the dev application", async () => {
await config.applications.publish(config.context._id) await config.applications.publish(config.context._id)
const [response, deletion] = await config.applications.delete(config.context._id) const [response, deletion] = await config.applications.delete(
config.context._id
)
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(deletion._id).toEqual(config.context._id) expect(deletion._id).toEqual(config.context._id)