Merge pull request #13345 from Budibase/feature/onboarding
[Changed] Identity override for event publish + BPM literals
This commit is contained in:
commit
d947d91721
|
@ -1,4 +1,4 @@
|
||||||
import { Event } from "@budibase/types"
|
import { Event, Identity } from "@budibase/types"
|
||||||
import { processors } from "./processors"
|
import { processors } from "./processors"
|
||||||
import identification from "./identification"
|
import identification from "./identification"
|
||||||
import * as backfill from "./backfill"
|
import * as backfill from "./backfill"
|
||||||
|
@ -7,12 +7,19 @@ import { publishAsyncEvent } from "./asyncEvents"
|
||||||
export const publishEvent = async (
|
export const publishEvent = async (
|
||||||
event: Event,
|
event: Event,
|
||||||
properties: any,
|
properties: any,
|
||||||
timestamp?: string | number
|
timestamp?: string | number,
|
||||||
|
identityOverride?: Identity
|
||||||
) => {
|
) => {
|
||||||
// in future this should use async events via a distributed queue.
|
// in future this should use async events via a distributed queue.
|
||||||
const identity = await identification.getCurrentIdentity()
|
const identity =
|
||||||
|
identityOverride || (await identification.getCurrentIdentity())
|
||||||
|
|
||||||
|
// Backfilling is get from the user cache, but when we override the identity cache is not available. Overrides are
|
||||||
|
// normally performed in automatic actions or operations in async flows (BPM) where the user session is not available.
|
||||||
|
const backfilling = identityOverride
|
||||||
|
? false
|
||||||
|
: await backfill.isBackfillingEvent(event)
|
||||||
|
|
||||||
const backfilling = await backfill.isBackfillingEvent(event)
|
|
||||||
// no backfill - send the event and exit
|
// no backfill - send the event and exit
|
||||||
if (!backfilling) {
|
if (!backfilling) {
|
||||||
// send off async events if required
|
// send off async events if required
|
||||||
|
|
|
@ -5,13 +5,19 @@ import {
|
||||||
AccountCreatedEvent,
|
AccountCreatedEvent,
|
||||||
AccountDeletedEvent,
|
AccountDeletedEvent,
|
||||||
AccountVerifiedEvent,
|
AccountVerifiedEvent,
|
||||||
|
Identity,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
async function created(account: Account) {
|
async function created(account: Account, identityOverride?: Identity) {
|
||||||
const properties: AccountCreatedEvent = {
|
const properties: AccountCreatedEvent = {
|
||||||
tenantId: account.tenantId,
|
tenantId: account.tenantId,
|
||||||
}
|
}
|
||||||
await publishEvent(Event.ACCOUNT_CREATED, properties)
|
await publishEvent(
|
||||||
|
Event.ACCOUNT_CREATED,
|
||||||
|
properties,
|
||||||
|
undefined,
|
||||||
|
identityOverride
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleted(account: Account) {
|
async function deleted(account: Account) {
|
||||||
|
|
|
@ -500,13 +500,13 @@ export class UserDB {
|
||||||
|
|
||||||
static async createAdminUser(
|
static async createAdminUser(
|
||||||
email: string,
|
email: string,
|
||||||
password: string,
|
|
||||||
tenantId: string,
|
tenantId: string,
|
||||||
|
password?: string,
|
||||||
opts?: CreateAdminUserOpts
|
opts?: CreateAdminUserOpts
|
||||||
) {
|
) {
|
||||||
const user: User = {
|
const user: User = {
|
||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password,
|
||||||
createdAt: Date.now(),
|
createdAt: Date.now(),
|
||||||
roles: {},
|
roles: {},
|
||||||
builder: {
|
builder: {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
export { OperatorOptions, SqlNumberTypeRangeMap } from "@budibase/shared-core"
|
export { OperatorOptions, SqlNumberTypeRangeMap } from "@budibase/shared-core"
|
||||||
export { Feature as Features } from "@budibase/types"
|
export { Feature as Features } from "@budibase/types"
|
||||||
|
import { BpmCorrelationKey } from "@budibase/shared-core"
|
||||||
|
|
||||||
// Cookie names
|
// Cookie names
|
||||||
export const Cookies = {
|
export const Cookies = {
|
||||||
|
@ -10,6 +11,7 @@ export const Cookies = {
|
||||||
CurrentApp: "budibase:currentapp",
|
CurrentApp: "budibase:currentapp",
|
||||||
ReturnUrl: "budibase:returnurl",
|
ReturnUrl: "budibase:returnurl",
|
||||||
AccountReturnUrl: "budibase:account:returnurl",
|
AccountReturnUrl: "budibase:account:returnurl",
|
||||||
|
OnboardingProcessCorrelationKey: BpmCorrelationKey.ONBOARDING,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Table names
|
// Table names
|
||||||
|
|
|
@ -159,3 +159,22 @@ export const InvalidFileExtensions = [
|
||||||
"wsh",
|
"wsh",
|
||||||
"zip",
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export enum BpmCorrelationKey {
|
||||||
|
ONBOARDING = "budibase:onboarding:correlationkey",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum BpmInstanceKey {
|
||||||
|
ONBOARDING = "budibase:onboarding:instancekey",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum BpmStatusKey {
|
||||||
|
ONBOARDING = "budibase:onboarding:status",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum BpmStatusValue {
|
||||||
|
STARTED = "started",
|
||||||
|
COMPLETING_ACCOUNT_INFO = "completing_account_info",
|
||||||
|
VERIFYING_EMAIL = "verifying_email",
|
||||||
|
COMPLETED = "completed",
|
||||||
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ export interface SearchUsersRequest {
|
||||||
|
|
||||||
export interface CreateAdminUserRequest {
|
export interface CreateAdminUserRequest {
|
||||||
email: string
|
email: string
|
||||||
password: string
|
password?: string
|
||||||
tenantId: string
|
tenantId: string
|
||||||
ssoId?: string
|
ssoId?: string
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,8 @@ export const adminUser = async (
|
||||||
try {
|
try {
|
||||||
const finalUser = await userSdk.db.createAdminUser(
|
const finalUser = await userSdk.db.createAdminUser(
|
||||||
email,
|
email,
|
||||||
password,
|
|
||||||
tenantId,
|
tenantId,
|
||||||
|
password,
|
||||||
{
|
{
|
||||||
ssoId,
|
ssoId,
|
||||||
hashPassword,
|
hashPassword,
|
||||||
|
|
|
@ -7,12 +7,13 @@ import { users } from "../validation"
|
||||||
import * as selfController from "../../controllers/global/self"
|
import * as selfController from "../../controllers/global/self"
|
||||||
|
|
||||||
const router: Router = new Router()
|
const router: Router = new Router()
|
||||||
|
const OPTIONAL_STRING = Joi.string().optional().allow(null).allow("")
|
||||||
|
|
||||||
function buildAdminInitValidation() {
|
function buildAdminInitValidation() {
|
||||||
return auth.joiValidator.body(
|
return auth.joiValidator.body(
|
||||||
Joi.object({
|
Joi.object({
|
||||||
email: Joi.string().required(),
|
email: Joi.string().required(),
|
||||||
password: Joi.string(),
|
password: OPTIONAL_STRING,
|
||||||
tenantId: Joi.string().required(),
|
tenantId: Joi.string().required(),
|
||||||
ssoId: Joi.string(),
|
ssoId: Joi.string(),
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
import TestConfiguration from "../../config/TestConfiguration"
|
|
||||||
import * as fixtures from "../../fixtures"
|
|
||||||
|
|
||||||
describe("Internal API - Application creation", () => {
|
|
||||||
const config = new TestConfiguration()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Get applications without applications", async () => {
|
|
||||||
await config.api.apps.fetchEmptyAppList()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Get all Applications after creating an application", async () => {
|
|
||||||
await config.api.apps.create({
|
|
||||||
...fixtures.apps.generateApp(),
|
|
||||||
useTemplate: "false",
|
|
||||||
})
|
|
||||||
|
|
||||||
await config.api.apps.fetchAllApplications()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Get application details", async () => {
|
|
||||||
const app = await config.createApp({
|
|
||||||
...fixtures.apps.generateApp(),
|
|
||||||
useTemplate: "false",
|
|
||||||
})
|
|
||||||
|
|
||||||
const [appPackageResponse, appPackageJson] =
|
|
||||||
await config.api.apps.getAppPackage(app.appId!)
|
|
||||||
expect(appPackageJson.application.name).toEqual(app.name)
|
|
||||||
expect(appPackageJson.application.version).toEqual(app.version)
|
|
||||||
expect(appPackageJson.application.url).toEqual(app.url)
|
|
||||||
expect(appPackageJson.application.tenantId).toEqual(app.tenantId)
|
|
||||||
expect(appPackageJson.application.status).toEqual(app.status)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,19 +0,0 @@
|
||||||
import TestConfiguration from "../../config/TestConfiguration"
|
|
||||||
|
|
||||||
describe("Internal API - Application creation, update, publish and delete", () => {
|
|
||||||
const config = new TestConfiguration()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("DELETE - Delete an application", async () => {
|
|
||||||
const app = await config.createApp()
|
|
||||||
|
|
||||||
await config.api.apps.delete(app.appId!)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,54 +0,0 @@
|
||||||
import TestConfiguration from "../../config/TestConfiguration"
|
|
||||||
import { db } from "@budibase/backend-core"
|
|
||||||
import * as fixtures from "../../fixtures"
|
|
||||||
|
|
||||||
describe("Internal API - Application creation, update, publish and delete", () => {
|
|
||||||
const config = new TestConfiguration()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Publish app", async () => {
|
|
||||||
// create the app
|
|
||||||
const app = await config.createApp(fixtures.apps.appFromTemplate())
|
|
||||||
|
|
||||||
// check preview renders
|
|
||||||
await config.api.apps.canRender()
|
|
||||||
|
|
||||||
// publish app
|
|
||||||
await config.api.apps.publish(app.appId)
|
|
||||||
|
|
||||||
// check published app renders
|
|
||||||
config.state.appId = db.getProdAppID(app.appId!)
|
|
||||||
await config.api.apps.canRender()
|
|
||||||
|
|
||||||
// unpublish app
|
|
||||||
await config.api.apps.unpublish(app.appId!)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Sync application before deployment", async () => {
|
|
||||||
const app = await config.createApp()
|
|
||||||
|
|
||||||
const [syncResponse, sync] = await config.api.apps.sync(app.appId!)
|
|
||||||
expect(sync).toEqual({
|
|
||||||
message: "App sync completed successfully.",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Sync application after deployment", async () => {
|
|
||||||
const app = await config.createApp()
|
|
||||||
|
|
||||||
// publish app
|
|
||||||
await config.api.apps.publish(app._id)
|
|
||||||
|
|
||||||
const [syncResponse, sync] = await config.api.apps.sync(app.appId!)
|
|
||||||
expect(sync).toEqual({
|
|
||||||
message: "App sync completed successfully.",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,45 +0,0 @@
|
||||||
import TestConfiguration from "../../config/TestConfiguration"
|
|
||||||
import { generator } from "../../../shared"
|
|
||||||
import * as fixtures from "../../fixtures"
|
|
||||||
|
|
||||||
describe("Internal API - Application creation, update, publish and delete", () => {
|
|
||||||
const config = new TestConfiguration()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Update an application", async () => {
|
|
||||||
const app = await config.createApp()
|
|
||||||
|
|
||||||
await config.api.apps.rename(app.appId!, app.name!, {
|
|
||||||
name: generator.word(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Revert Changes without changes", async () => {
|
|
||||||
const app = await config.createApp()
|
|
||||||
|
|
||||||
await config.api.apps.revertUnpublished(app.appId!)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Revert Changes", async () => {
|
|
||||||
const app = await config.createApp()
|
|
||||||
|
|
||||||
// publish app
|
|
||||||
await config.api.apps.publish(app._id)
|
|
||||||
|
|
||||||
// Change/add component to the app
|
|
||||||
await config.api.screens.create(fixtures.screens.generateScreen("BASIC"))
|
|
||||||
|
|
||||||
// // Revert the app to published state
|
|
||||||
await config.api.apps.revertPublished(app.appId!)
|
|
||||||
|
|
||||||
// Check screen is removed
|
|
||||||
await config.api.apps.getRoutes()
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,51 +0,0 @@
|
||||||
import TestConfiguration from "../../config/TestConfiguration"
|
|
||||||
import * as fixtures from "../../fixtures"
|
|
||||||
|
|
||||||
describe("Internal API - /screens endpoints", () => {
|
|
||||||
const config = new TestConfiguration()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Create a screen with each role type", async () => {
|
|
||||||
// Create app
|
|
||||||
await config.createApp()
|
|
||||||
|
|
||||||
// Create Screen
|
|
||||||
const roleArray = ["BASIC", "POWER", "ADMIN", "PUBLIC"]
|
|
||||||
for (let role in roleArray) {
|
|
||||||
const [response, screen] = await config.api.screens.create(
|
|
||||||
fixtures.screens.generateScreen(roleArray[role])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Get screens", async () => {
|
|
||||||
// Create app
|
|
||||||
await config.createApp()
|
|
||||||
|
|
||||||
// Create Screen
|
|
||||||
await config.api.screens.create(fixtures.screens.generateScreen("BASIC"))
|
|
||||||
|
|
||||||
// Check screen exists
|
|
||||||
await config.api.apps.getRoutes(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Delete a screen", async () => {
|
|
||||||
// Create app
|
|
||||||
await config.createApp()
|
|
||||||
|
|
||||||
// Create Screen
|
|
||||||
const [screenResponse, screen] = await config.api.screens.create(
|
|
||||||
fixtures.screens.generateScreen("BASIC")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Delete Screen
|
|
||||||
await config.api.screens.delete(screen._id!, screen._rev!)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,133 +0,0 @@
|
||||||
import TestConfiguration from "../../config/TestConfiguration"
|
|
||||||
import { generator } from "../../../shared"
|
|
||||||
import * as fixtures from "../../fixtures"
|
|
||||||
|
|
||||||
describe("Internal API - Table Operations", () => {
|
|
||||||
const config = new TestConfiguration()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Create and delete table, columns and rows", async () => {
|
|
||||||
// create the app
|
|
||||||
await config.createApp(fixtures.apps.appFromTemplate())
|
|
||||||
|
|
||||||
// Get current tables: expect 2 in this template
|
|
||||||
await config.api.tables.getAll(2)
|
|
||||||
|
|
||||||
// Add new table
|
|
||||||
const [createdTableResponse, createdTableData] =
|
|
||||||
await config.api.tables.save(fixtures.tables.generateTable())
|
|
||||||
|
|
||||||
//Table was added
|
|
||||||
await config.api.tables.getAll(3)
|
|
||||||
|
|
||||||
//Get information about the table
|
|
||||||
await config.api.tables.getTableById(createdTableData._id!)
|
|
||||||
|
|
||||||
//Add Column to table
|
|
||||||
const newColumn =
|
|
||||||
fixtures.tables.generateNewColumnForTable(createdTableData)
|
|
||||||
const [addColumnResponse, addColumnData] = await config.api.tables.save(
|
|
||||||
newColumn,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
//Add Row to table
|
|
||||||
const newRow = fixtures.rows.generateNewRowForTable(addColumnData._id!)
|
|
||||||
await config.api.rows.add(addColumnData._id!, newRow)
|
|
||||||
|
|
||||||
//Get Row from table
|
|
||||||
const [getRowResponse, getRowData] = await config.api.rows.getAll(
|
|
||||||
addColumnData._id!
|
|
||||||
)
|
|
||||||
|
|
||||||
//Delete Row from table
|
|
||||||
const rowToDelete = {
|
|
||||||
rows: [getRowData[0]],
|
|
||||||
}
|
|
||||||
const [deleteRowResponse, deleteRowData] = await config.api.rows.delete(
|
|
||||||
addColumnData._id!,
|
|
||||||
rowToDelete
|
|
||||||
)
|
|
||||||
expect(deleteRowData[0]._id).toEqual(getRowData[0]._id)
|
|
||||||
|
|
||||||
//Delete the table
|
|
||||||
const [deleteTableResponse, deleteTable] = await config.api.tables.delete(
|
|
||||||
addColumnData._id!,
|
|
||||||
addColumnData._rev!
|
|
||||||
)
|
|
||||||
|
|
||||||
//Table was deleted
|
|
||||||
await config.api.tables.getAll(2)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Search and pagination", async () => {
|
|
||||||
// create the app
|
|
||||||
await config.createApp(fixtures.apps.appFromTemplate())
|
|
||||||
|
|
||||||
// Get current tables: expect 2 in this template
|
|
||||||
await config.api.tables.getAll(2)
|
|
||||||
|
|
||||||
// Add new table
|
|
||||||
const [createdTableResponse, createdTableData] =
|
|
||||||
await config.api.tables.save(fixtures.tables.generateTable())
|
|
||||||
|
|
||||||
//Table was added
|
|
||||||
await config.api.tables.getAll(3)
|
|
||||||
|
|
||||||
//Get information about the table
|
|
||||||
await config.api.tables.getTableById(createdTableData._id!)
|
|
||||||
|
|
||||||
//Add Column to table
|
|
||||||
const newColumn =
|
|
||||||
fixtures.tables.generateNewColumnForTable(createdTableData)
|
|
||||||
const [addColumnResponse, addColumnData] = await config.api.tables.save(
|
|
||||||
newColumn,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
//Add Row to table
|
|
||||||
let newRow = fixtures.rows.generateNewRowForTable(addColumnData._id!)
|
|
||||||
await config.api.rows.add(addColumnData._id!, newRow)
|
|
||||||
|
|
||||||
//Search single row
|
|
||||||
await config.api.rows.searchNoPagination(
|
|
||||||
createdTableData._id!,
|
|
||||||
fixtures.rows.searchBody(createdTableData.primaryDisplay!)
|
|
||||||
)
|
|
||||||
|
|
||||||
//Add 10 more rows
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
let newRow = fixtures.rows.generateNewRowForTable(addColumnData._id!)
|
|
||||||
await config.api.rows.add(addColumnData._id!, newRow)
|
|
||||||
}
|
|
||||||
|
|
||||||
//Search rows with pagination
|
|
||||||
const [allRowsResponse, allRowsJson] =
|
|
||||||
await config.api.rows.searchWithPagination(
|
|
||||||
createdTableData._id!,
|
|
||||||
fixtures.rows.searchBody(createdTableData.primaryDisplay!)
|
|
||||||
)
|
|
||||||
|
|
||||||
//Delete Rows from table
|
|
||||||
const rowToDelete = {
|
|
||||||
rows: [allRowsJson],
|
|
||||||
}
|
|
||||||
const [deleteRowResponse, deleteRowData] = await config.api.rows.delete(
|
|
||||||
createdTableData._id!,
|
|
||||||
rowToDelete
|
|
||||||
)
|
|
||||||
|
|
||||||
//Search single row
|
|
||||||
await config.api.rows.searchWithPagination(
|
|
||||||
createdTableData._id!,
|
|
||||||
fixtures.rows.searchBody(createdTableData.primaryDisplay!)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,104 +0,0 @@
|
||||||
import TestConfiguration from "../../config/TestConfiguration"
|
|
||||||
import { User } from "@budibase/types"
|
|
||||||
import { db } from "@budibase/backend-core"
|
|
||||||
import * as fixtures from "../../fixtures"
|
|
||||||
|
|
||||||
describe("Internal API - App Specific Roles & Permissions", () => {
|
|
||||||
const config = new TestConfiguration()
|
|
||||||
|
|
||||||
// Before each test, login as admin. Some tests will require login as a different user
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Add BASIC user to app", async () => {
|
|
||||||
const appUser = fixtures.users.generateUser()
|
|
||||||
expect(appUser[0].builder?.global).toEqual(false)
|
|
||||||
expect(appUser[0].admin?.global).toEqual(false)
|
|
||||||
const [createUserResponse, createUserJson] =
|
|
||||||
await config.api.users.addMultiple(appUser)
|
|
||||||
|
|
||||||
const app = await config.createApp(fixtures.apps.appFromTemplate())
|
|
||||||
|
|
||||||
const [userInfoResponse, userInfoJson] = await config.api.users.getInfo(
|
|
||||||
createUserJson.created.successful[0]._id
|
|
||||||
)
|
|
||||||
const body: User = {
|
|
||||||
...userInfoJson,
|
|
||||||
roles: {
|
|
||||||
[app.appId!]: "BASIC",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
await config.api.users.updateInfo(body)
|
|
||||||
|
|
||||||
const [changedUserInfoResponse, changedUserInfoJson] =
|
|
||||||
await config.api.users.getInfo(createUserJson.created.successful[0]._id)
|
|
||||||
expect(changedUserInfoJson.roles[app.appId!]).toBeDefined()
|
|
||||||
expect(changedUserInfoJson.roles[app.appId!]).toEqual("BASIC")
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Add ADMIN user to app", async () => {
|
|
||||||
// Create a user with ADMIN role and check if it was created successfully
|
|
||||||
const adminUser = fixtures.users.generateUser(1, "admin")
|
|
||||||
expect(adminUser[0].builder?.global).toEqual(true)
|
|
||||||
expect(adminUser[0].admin?.global).toEqual(true)
|
|
||||||
const [createUserResponse, createUserJson] =
|
|
||||||
await config.api.users.addMultiple(adminUser)
|
|
||||||
|
|
||||||
// const app = await config.createApp(fixtures.apps.appFromTemplate())
|
|
||||||
const app = await config.createApp(fixtures.apps.appFromTemplate())
|
|
||||||
|
|
||||||
const [userInfoResponse, userInfoJson] = await config.api.users.getInfo(
|
|
||||||
createUserJson.created.successful[0]._id
|
|
||||||
)
|
|
||||||
const body: User = {
|
|
||||||
...userInfoJson,
|
|
||||||
roles: {
|
|
||||||
[app.appId!]: "ADMIN",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
await config.api.users.updateInfo(body)
|
|
||||||
|
|
||||||
const [changedUserInfoResponse, changedUserInfoJson] =
|
|
||||||
await config.api.users.getInfo(createUserJson.created.successful[0]._id)
|
|
||||||
expect(changedUserInfoJson.roles[app.appId!]).toBeDefined()
|
|
||||||
expect(changedUserInfoJson.roles[app.appId!]).toEqual("ADMIN")
|
|
||||||
|
|
||||||
// publish app
|
|
||||||
await config.api.apps.publish(app.appId)
|
|
||||||
// check published app renders
|
|
||||||
config.state.appId = db.getProdAppID(app.appId!)
|
|
||||||
await config.api.apps.canRender()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Add POWER user to app", async () => {
|
|
||||||
const powerUser = fixtures.users.generateUser(1, "developer")
|
|
||||||
expect(powerUser[0].builder?.global).toEqual(true)
|
|
||||||
|
|
||||||
const [createUserResponse, createUserJson] =
|
|
||||||
await config.api.users.addMultiple(powerUser)
|
|
||||||
|
|
||||||
const app = await config.createApp()
|
|
||||||
|
|
||||||
const [userInfoResponse, userInfoJson] = await config.api.users.getInfo(
|
|
||||||
createUserJson.created.successful[0]._id
|
|
||||||
)
|
|
||||||
const body: User = {
|
|
||||||
...userInfoJson,
|
|
||||||
roles: {
|
|
||||||
[app.appId!]: "POWER",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
await config.api.users.updateInfo(body)
|
|
||||||
|
|
||||||
// Get the user information again and check if the role was added
|
|
||||||
const [changedUserInfoResponse, changedUserInfoJson] =
|
|
||||||
await config.api.users.getInfo(createUserJson.created.successful[0]._id)
|
|
||||||
expect(changedUserInfoJson.roles[app.appId!]).toBeDefined()
|
|
||||||
expect(changedUserInfoJson.roles[app.appId!]).toEqual("POWER")
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,90 +0,0 @@
|
||||||
import TestConfiguration from "../../config/TestConfiguration"
|
|
||||||
import { User } from "@budibase/types"
|
|
||||||
import * as fixtures from "./../../fixtures"
|
|
||||||
|
|
||||||
describe("Internal API - User Management & Permissions", () => {
|
|
||||||
const config = new TestConfiguration()
|
|
||||||
|
|
||||||
// Before each test, login as admin. Some tests will require login as a different user
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Add Users with different roles", async () => {
|
|
||||||
// Get all users
|
|
||||||
await config.api.users.search()
|
|
||||||
|
|
||||||
// Get all roles
|
|
||||||
await config.api.users.getRoles()
|
|
||||||
|
|
||||||
// Add users with each role
|
|
||||||
const admin = fixtures.users.generateUser(1, "admin")
|
|
||||||
expect(admin[0].builder?.global).toEqual(true)
|
|
||||||
expect(admin[0].admin?.global).toEqual(true)
|
|
||||||
const developer = fixtures.users.generateUser(1, "developer")
|
|
||||||
expect(developer[0].builder?.global).toEqual(true)
|
|
||||||
const appUser = fixtures.users.generateUser(1, "appUser")
|
|
||||||
expect(appUser[0].builder?.global).toEqual(false)
|
|
||||||
expect(appUser[0].admin?.global).toEqual(false)
|
|
||||||
|
|
||||||
const userList = [...admin, ...developer, ...appUser]
|
|
||||||
|
|
||||||
await config.api.users.addMultiple(userList)
|
|
||||||
|
|
||||||
// Check users are added
|
|
||||||
const [allUsersResponse, allUsersJson] = await config.api.users.getAll()
|
|
||||||
expect(allUsersJson.length).toBeGreaterThan(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Delete User", async () => {
|
|
||||||
const appUser = fixtures.users.generateUser()
|
|
||||||
expect(appUser[0].builder?.global).toEqual(false)
|
|
||||||
expect(appUser[0].admin?.global).toEqual(false)
|
|
||||||
const [userResponse, userJson] = await config.api.users.addMultiple(appUser)
|
|
||||||
const userId = userJson.created.successful[0]._id
|
|
||||||
await config.api.users.delete(userId)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Reset Password", async () => {
|
|
||||||
const appUser = fixtures.users.generateUser()
|
|
||||||
expect(appUser[0].builder?.global).toEqual(false)
|
|
||||||
expect(appUser[0].admin?.global).toEqual(false)
|
|
||||||
const [userResponse, userJson] = await config.api.users.addMultiple(appUser)
|
|
||||||
const [userInfoResponse, userInfoJson] = await config.api.users.getInfo(
|
|
||||||
userJson.created.successful[0]._id
|
|
||||||
)
|
|
||||||
const body: User = {
|
|
||||||
...userInfoJson,
|
|
||||||
password: "newPassword",
|
|
||||||
}
|
|
||||||
await config.api.users.forcePasswordReset(body)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Change User information", async () => {
|
|
||||||
const appUser = fixtures.users.generateUser()
|
|
||||||
expect(appUser[0].builder?.global).toEqual(false)
|
|
||||||
expect(appUser[0].admin?.global).toEqual(false)
|
|
||||||
const [userResponse, userJson] = await config.api.users.addMultiple(appUser)
|
|
||||||
const [userInfoResponse, userInfoJson] = await config.api.users.getInfo(
|
|
||||||
userJson.created.successful[0]._id
|
|
||||||
)
|
|
||||||
const body: User = {
|
|
||||||
...userInfoJson,
|
|
||||||
firstName: "newFirstName",
|
|
||||||
lastName: "newLastName",
|
|
||||||
builder: {
|
|
||||||
global: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
await config.api.users.updateInfo(body)
|
|
||||||
|
|
||||||
const [changedUserInfoResponse, changedUserInfoJson] =
|
|
||||||
await config.api.users.getInfo(userJson.created.successful[0]._id)
|
|
||||||
expect(changedUserInfoJson.builder?.global).toBeDefined()
|
|
||||||
expect(changedUserInfoJson.builder?.global).toEqual(true)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,97 +0,0 @@
|
||||||
import { db as dbCore } from "@budibase/backend-core"
|
|
||||||
import { TestConfiguration } from "../../config"
|
|
||||||
import { Application } from "../../../types"
|
|
||||||
import * as fixtures from "../../fixtures"
|
|
||||||
|
|
||||||
describe("Public API - /applications endpoints", () => {
|
|
||||||
const config = new TestConfiguration<Application>()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
await config.createApp()
|
|
||||||
config.context = (await config.api.apps.read(config.state.appId!))[1]
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - Create an application", async () => {
|
|
||||||
const [response, app] = await config.api.apps.create(
|
|
||||||
fixtures.apps.generateApp()
|
|
||||||
)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(app._id).toBeDefined()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - Search applications", async () => {
|
|
||||||
const [response, apps] = await config.api.apps.search({
|
|
||||||
name: config.context.name,
|
|
||||||
})
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(apps[0]).toEqual(config.context)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("GET - Retrieve an application", async () => {
|
|
||||||
const [response, app] = await config.api.apps.read(config.context._id)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(app).toEqual(config.context)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("PUT - update an application", async () => {
|
|
||||||
config.context.name = "UpdatedName"
|
|
||||||
const [response, app] = await config.api.apps.update(
|
|
||||||
config.context._id,
|
|
||||||
config.context
|
|
||||||
)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(app.updatedAt).not.toEqual(config.context.updatedAt)
|
|
||||||
expect(app.name).toEqual(config.context.name)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - publish an application", async () => {
|
|
||||||
config.context.name = "UpdatedName"
|
|
||||||
const [response, deployment] = await config.api.apps.publish(
|
|
||||||
config.context._id
|
|
||||||
)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(deployment).toEqual({
|
|
||||||
status: "SUCCESS",
|
|
||||||
})
|
|
||||||
|
|
||||||
// Verify publish
|
|
||||||
const prodAppId = dbCore.getProdAppID(config.context._id)
|
|
||||||
const [_, publishedApp] = await config.api.apps.read(prodAppId)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(publishedApp._id).toEqual(prodAppId)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - unpublish a published application", async () => {
|
|
||||||
await config.api.apps.publish(config.context._id)
|
|
||||||
const [response] = await config.api.apps.unpublish(config.context._id)
|
|
||||||
expect(response).toHaveStatusCode(204)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - unpublish an unpublished application", async () => {
|
|
||||||
const [response] = await config.api.apps.unpublish(config.context._id)
|
|
||||||
expect(response).toHaveStatusCode(400)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("DELETE - delete a published application and the dev application", async () => {
|
|
||||||
await config.api.apps.publish(config.context._id)
|
|
||||||
const [response, deletion] = await config.api.apps.delete(
|
|
||||||
config.context._id
|
|
||||||
)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(deletion._id).toEqual(config.context._id)
|
|
||||||
|
|
||||||
// verify dev app deleted
|
|
||||||
const [devAppResponse] = await config.api.apps.read(config.context._id)
|
|
||||||
expect(devAppResponse).toHaveStatusCode(404)
|
|
||||||
|
|
||||||
// verify prod app deleted
|
|
||||||
const prodAppId = dbCore.getProdAppID(config.context._id)
|
|
||||||
const [publishedAppResponse] = await config.api.apps.read(prodAppId)
|
|
||||||
expect(publishedAppResponse).toHaveStatusCode(404)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,62 +0,0 @@
|
||||||
import { TestConfiguration } from "../../config"
|
|
||||||
import * as fixtures from "../../fixtures"
|
|
||||||
import { Row } from "../../../types"
|
|
||||||
|
|
||||||
describe("Public API - /rows endpoints", () => {
|
|
||||||
const config = new TestConfiguration<Row>()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
await config.createApp()
|
|
||||||
|
|
||||||
const [tResp, table] = await config.api.tables.seed()
|
|
||||||
config.state.tableId = table._id
|
|
||||||
|
|
||||||
const [rResp, row] = await config.api.rows.seed(table._id)
|
|
||||||
config.context = row
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - Create a row", async () => {
|
|
||||||
const [response, row] = await config.api.rows.create(
|
|
||||||
fixtures.rows.generateRow()
|
|
||||||
)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(row._id).toBeDefined()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - Search rows", async () => {
|
|
||||||
const [response, rows] = await config.api.rows.search({
|
|
||||||
query: {
|
|
||||||
string: {
|
|
||||||
testColumn: config.context.testColumn as string,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(rows.length).toEqual(1)
|
|
||||||
expect(rows[0]._id).toEqual(config.context._id)
|
|
||||||
expect(rows[0].tableId).toEqual(config.context.tableId)
|
|
||||||
expect(rows[0].testColumn).toEqual(config.context.testColumn)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("GET - Retrieve a row", async () => {
|
|
||||||
const [response, row] = await config.api.rows.read(config.context._id)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(row._id).toEqual(config.context._id)
|
|
||||||
expect(row.tableId).toEqual(config.context.tableId)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("PUT - update a row", async () => {
|
|
||||||
config.context.testColumn = "UpdatedName"
|
|
||||||
const [response, row] = await config.api.rows.update(
|
|
||||||
config.context._id,
|
|
||||||
config.context
|
|
||||||
)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(row.testColumn).toEqual(config.context.testColumn)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,51 +0,0 @@
|
||||||
import { TestConfiguration } from "../../config"
|
|
||||||
import * as fixtures from "../../fixtures"
|
|
||||||
import { Table } from "../../../types"
|
|
||||||
|
|
||||||
describe("Public API - /tables endpoints", () => {
|
|
||||||
const config = new TestConfiguration<Table>()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
await config.createApp()
|
|
||||||
|
|
||||||
const [tableResp, table] = await config.api.tables.seed()
|
|
||||||
config.context = table
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - Create a table", async () => {
|
|
||||||
const [response, table] = await config.api.tables.create(
|
|
||||||
fixtures.tables.generateTable()
|
|
||||||
)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(table._id).toBeDefined()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - Search tables", async () => {
|
|
||||||
const [response, tables] = await config.api.tables.search({
|
|
||||||
name: config.context.name,
|
|
||||||
})
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(tables[0]).toEqual(config.context)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("GET - Retrieve a table", async () => {
|
|
||||||
const [response, table] = await config.api.tables.read(config.context._id)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(table).toEqual(config.context)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("PUT - update a table", async () => {
|
|
||||||
config.context.name = "updatedName"
|
|
||||||
const [response, table] = await config.api.tables.update(
|
|
||||||
config.context._id,
|
|
||||||
config.context
|
|
||||||
)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(table).toEqual(config.context)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,49 +0,0 @@
|
||||||
import TestConfiguration from "../../config/TestConfiguration"
|
|
||||||
import * as fixtures from "../../fixtures"
|
|
||||||
import { User } from "../../../types"
|
|
||||||
|
|
||||||
describe("Public API - /users endpoints", () => {
|
|
||||||
const config = new TestConfiguration<User>()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await config.beforeAll()
|
|
||||||
const [_, user] = await config.api.users.seed()
|
|
||||||
config.context = user
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await config.afterAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - Create a user", async () => {
|
|
||||||
const [response, user] = await config.api.users.create(
|
|
||||||
fixtures.users.generateUser()
|
|
||||||
)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(user._id).toBeDefined()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("POST - Search users", async () => {
|
|
||||||
const [response, users] = await config.api.users.search({
|
|
||||||
name: config.context.email,
|
|
||||||
})
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(users[0]).toEqual(config.context)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("GET - Retrieve a user", async () => {
|
|
||||||
const [response, user] = await config.api.users.read(config.context._id)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(user).toEqual(config.context)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("PUT - update a user", async () => {
|
|
||||||
config.context.firstName = "Updated First Name"
|
|
||||||
const [response, user] = await config.api.users.update(
|
|
||||||
config.context._id,
|
|
||||||
config.context
|
|
||||||
)
|
|
||||||
expect(response).toHaveStatusCode(200)
|
|
||||||
expect(user).toEqual(config.context)
|
|
||||||
})
|
|
||||||
})
|
|
Loading…
Reference in New Issue