Merge branch 'nested-nav-links' of github.com:Budibase/budibase into nested-nav-links
This commit is contained in:
commit
c76fda35ab
|
@ -66,7 +66,8 @@ jobs:
|
||||||
# Run build all the projects
|
# Run build all the projects
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
yarn build
|
yarn build:oss
|
||||||
|
yarn build:account-portal
|
||||||
# Check the types of the projects built via esbuild
|
# Check the types of the projects built via esbuild
|
||||||
- name: Check types
|
- name: Check types
|
||||||
run: |
|
run: |
|
||||||
|
@ -231,27 +232,34 @@ jobs:
|
||||||
echo "pro_commit=$pro_commit"
|
echo "pro_commit=$pro_commit"
|
||||||
echo "pro_commit=$pro_commit" >> "$GITHUB_OUTPUT"
|
echo "pro_commit=$pro_commit" >> "$GITHUB_OUTPUT"
|
||||||
echo "base_commit=$base_commit"
|
echo "base_commit=$base_commit"
|
||||||
echo "base_commit=$base_commit" >> "$GITHUB_OUTPUT"
|
|
||||||
|
base_commit_excluding_merges=$(git log --no-merges -n 1 --format=format:%H $base_commit)
|
||||||
|
echo "base_commit_excluding_merges=$base_commit_excluding_merges"
|
||||||
|
echo "base_commit_excluding_merges=$base_commit_excluding_merges" >> "$GITHUB_OUTPUT"
|
||||||
else
|
else
|
||||||
echo "Nothing to do - branch to branch merge."
|
echo "Nothing to do - branch to branch merge."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Check submodule merged to base branch
|
- name: Check submodule merged and latest on base branch
|
||||||
if: ${{ steps.get_pro_commits.outputs.base_commit != '' }}
|
if: ${{ steps.get_pro_commits.outputs.base_commit_excluding_merges != '' }}
|
||||||
uses: actions/github-script@v7
|
run: |
|
||||||
with:
|
cd packages/pro
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
base_commit_excluding_merges='${{ steps.get_pro_commits.outputs.base_commit_excluding_merges }}'
|
||||||
script: |
|
pro_commit='${{ steps.get_pro_commits.outputs.pro_commit }}'
|
||||||
const submoduleCommit = '${{ steps.get_pro_commits.outputs.pro_commit }}';
|
|
||||||
const baseCommit = '${{ steps.get_pro_commits.outputs.base_commit }}';
|
|
||||||
|
|
||||||
if (submoduleCommit !== baseCommit) {
|
any_commit=$(git log --no-merges $base_commit_excluding_merges...$pro_commit)
|
||||||
console.error('Submodule commit does not match the latest commit on the "${{ steps.get_pro_commits.outputs.target_branch }}" branch.');
|
|
||||||
console.error('Refer to the pro repo to merge your changes: https://github.com/Budibase/budibase-pro/blob/master/docs/getting_started.md')
|
if [ -n "$any_commit" ]; then
|
||||||
process.exit(1);
|
echo $any_commit
|
||||||
} else {
|
|
||||||
console.log('All good, the submodule had been merged and setup correctly!')
|
echo "An error occurred: <error_message>"
|
||||||
}
|
echo 'Submodule commit does not match the latest commit on the "${{ steps.get_pro_commits.outputs.target_branch }}" branch.'
|
||||||
|
echo 'Refer to the pro repo to merge your changes: https://github.com/Budibase/budibase-pro/blob/master/docs/getting_started.md'
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo 'All good, the submodule had been merged and setup correctly!'
|
||||||
|
fi
|
||||||
|
|
||||||
check-accountportal-submodule:
|
check-accountportal-submodule:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "2.22.12",
|
"version": "2.22.13",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*",
|
"packages/*",
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
"get-past-client-version": "node scripts/getPastClientVersion.js",
|
"get-past-client-version": "node scripts/getPastClientVersion.js",
|
||||||
"setup": "git config submodule.recurse true && git submodule update && node ./hosting/scripts/setup.js && yarn && yarn build && yarn dev",
|
"setup": "git config submodule.recurse true && git submodule update && node ./hosting/scripts/setup.js && yarn && yarn build && yarn dev",
|
||||||
"build": "NODE_OPTIONS=--max-old-space-size=1500 lerna run build --stream",
|
"build": "NODE_OPTIONS=--max-old-space-size=1500 lerna run build --stream",
|
||||||
|
"build:oss": "NODE_OPTIONS=--max-old-space-size=1500 lerna run build --stream --ignore @budibase/account-portal --ignore @budibase/account-portal-server --ignore @budibase/account-portal-ui",
|
||||||
|
"build:account-portal": "NODE_OPTIONS=--max-old-space-size=1500 lerna run build --stream --scope @budibase/account-portal --scope @budibase/account-portal-server --scope @budibase/account-portal-ui",
|
||||||
"build:dev": "lerna run --stream prebuild && yarn nx run-many --target=build --output-style=dynamic --watch --preserveWatchOutput",
|
"build:dev": "lerna run --stream prebuild && yarn nx run-many --target=build --output-style=dynamic --watch --preserveWatchOutput",
|
||||||
"check:types": "lerna run check:types",
|
"check:types": "lerna run check:types",
|
||||||
"build:sdk": "lerna run --stream build:sdk",
|
"build:sdk": "lerna run --stream build:sdk",
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit f5b467b6b1c55c48847545db41be7b1c035e167a
|
Subproject commit 63ce32bca871f0a752323f5f7ebb5ec16bbbacc3
|
|
@ -20,7 +20,7 @@ export async function lookupTenantId(userId: string) {
|
||||||
return user.tenantId
|
return user.tenantId
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getUserDoc(emailOrId: string): Promise<PlatformUser> {
|
export async function getUserDoc(emailOrId: string): Promise<PlatformUser> {
|
||||||
const db = getPlatformDB()
|
const db = getPlatformDB()
|
||||||
return db.get(emailOrId)
|
return db.get(emailOrId)
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,17 @@ async function addUserDoc(emailOrId: string, newDocFn: () => PlatformUser) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function addSsoUser(
|
||||||
|
ssoId: string,
|
||||||
|
email: string,
|
||||||
|
userId: string,
|
||||||
|
tenantId: string
|
||||||
|
) {
|
||||||
|
return addUserDoc(ssoId, () =>
|
||||||
|
newUserSsoIdDoc(ssoId, email, userId, tenantId)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export async function addUser(
|
export async function addUser(
|
||||||
tenantId: string,
|
tenantId: string,
|
||||||
userId: string,
|
userId: string,
|
||||||
|
@ -91,9 +102,7 @@ export async function addUser(
|
||||||
]
|
]
|
||||||
|
|
||||||
if (ssoId) {
|
if (ssoId) {
|
||||||
promises.push(
|
promises.push(addSsoUser(ssoId, email, userId, tenantId))
|
||||||
addUserDoc(ssoId, () => newUserSsoIdDoc(ssoId, email, userId, tenantId))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(promises)
|
await Promise.all(promises)
|
||||||
|
|
|
@ -12,6 +12,13 @@ export default {
|
||||||
format: "esm",
|
format: "esm",
|
||||||
file: "dist/bbui.es.js",
|
file: "dist/bbui.es.js",
|
||||||
},
|
},
|
||||||
|
onwarn(warning, warn) {
|
||||||
|
// suppress eval warnings
|
||||||
|
if (warning.code === "EVAL") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
warn(warning)
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
resolve(),
|
resolve(),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
|
|
|
@ -45,7 +45,8 @@ export default {
|
||||||
onwarn(warning, warn) {
|
onwarn(warning, warn) {
|
||||||
if (
|
if (
|
||||||
warning.code === "THIS_IS_UNDEFINED" ||
|
warning.code === "THIS_IS_UNDEFINED" ||
|
||||||
warning.code === "CIRCULAR_DEPENDENCY"
|
warning.code === "CIRCULAR_DEPENDENCY" ||
|
||||||
|
warning.code === "EVAL"
|
||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit f8e8f87bd52081e1303a5ae92c432ea5b38f3bb4
|
Subproject commit 6b62505be0c0b50a57b4f4980d86541ebdc86428
|
|
@ -9,6 +9,7 @@ import {
|
||||||
QueryType,
|
QueryType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { db as dbCore } from "@budibase/backend-core"
|
import { db as dbCore } from "@budibase/backend-core"
|
||||||
|
import { HOST_ADDRESS } from "./utils"
|
||||||
|
|
||||||
interface CouchDBConfig {
|
interface CouchDBConfig {
|
||||||
url: string
|
url: string
|
||||||
|
@ -28,7 +29,7 @@ const SCHEMA: Integration = {
|
||||||
url: {
|
url: {
|
||||||
type: DatasourceFieldType.STRING,
|
type: DatasourceFieldType.STRING,
|
||||||
required: true,
|
required: true,
|
||||||
default: "http://localhost:5984",
|
default: `http://${HOST_ADDRESS}:5984`,
|
||||||
},
|
},
|
||||||
database: {
|
database: {
|
||||||
type: DatasourceFieldType.STRING,
|
type: DatasourceFieldType.STRING,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
import { Client, ClientOptions } from "@elastic/elasticsearch"
|
import { Client, ClientOptions } from "@elastic/elasticsearch"
|
||||||
|
import { HOST_ADDRESS } from "./utils"
|
||||||
|
|
||||||
interface ElasticsearchConfig {
|
interface ElasticsearchConfig {
|
||||||
url: string
|
url: string
|
||||||
|
@ -29,7 +30,7 @@ const SCHEMA: Integration = {
|
||||||
url: {
|
url: {
|
||||||
type: DatasourceFieldType.STRING,
|
type: DatasourceFieldType.STRING,
|
||||||
required: true,
|
required: true,
|
||||||
default: "http://localhost:9200",
|
default: `http://${HOST_ADDRESS}:9200`,
|
||||||
},
|
},
|
||||||
ssl: {
|
ssl: {
|
||||||
type: DatasourceFieldType.BOOLEAN,
|
type: DatasourceFieldType.BOOLEAN,
|
||||||
|
|
|
@ -22,6 +22,7 @@ import {
|
||||||
finaliseExternalTables,
|
finaliseExternalTables,
|
||||||
SqlClient,
|
SqlClient,
|
||||||
checkExternalTables,
|
checkExternalTables,
|
||||||
|
HOST_ADDRESS,
|
||||||
} from "./utils"
|
} from "./utils"
|
||||||
import Sql from "./base/sql"
|
import Sql from "./base/sql"
|
||||||
import { MSSQLTablesResponse, MSSQLColumn } from "./base/types"
|
import { MSSQLTablesResponse, MSSQLColumn } from "./base/types"
|
||||||
|
@ -88,7 +89,6 @@ const SCHEMA: Integration = {
|
||||||
user: {
|
user: {
|
||||||
type: DatasourceFieldType.STRING,
|
type: DatasourceFieldType.STRING,
|
||||||
required: true,
|
required: true,
|
||||||
default: "localhost",
|
|
||||||
},
|
},
|
||||||
password: {
|
password: {
|
||||||
type: DatasourceFieldType.PASSWORD,
|
type: DatasourceFieldType.PASSWORD,
|
||||||
|
@ -96,7 +96,7 @@ const SCHEMA: Integration = {
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
type: DatasourceFieldType.STRING,
|
type: DatasourceFieldType.STRING,
|
||||||
default: "localhost",
|
default: HOST_ADDRESS,
|
||||||
},
|
},
|
||||||
port: {
|
port: {
|
||||||
type: DatasourceFieldType.NUMBER,
|
type: DatasourceFieldType.NUMBER,
|
||||||
|
|
|
@ -22,6 +22,7 @@ import {
|
||||||
InsertManyResult,
|
InsertManyResult,
|
||||||
} from "mongodb"
|
} from "mongodb"
|
||||||
import environment from "../environment"
|
import environment from "../environment"
|
||||||
|
import { HOST_ADDRESS } from "./utils"
|
||||||
|
|
||||||
export interface MongoDBConfig {
|
export interface MongoDBConfig {
|
||||||
connectionString: string
|
connectionString: string
|
||||||
|
@ -51,7 +52,7 @@ const getSchema = () => {
|
||||||
connectionString: {
|
connectionString: {
|
||||||
type: DatasourceFieldType.STRING,
|
type: DatasourceFieldType.STRING,
|
||||||
required: true,
|
required: true,
|
||||||
default: "mongodb://localhost:27017",
|
default: `mongodb://${HOST_ADDRESS}:27017`,
|
||||||
display: "Connection string",
|
display: "Connection string",
|
||||||
},
|
},
|
||||||
db: {
|
db: {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
generateColumnDefinition,
|
generateColumnDefinition,
|
||||||
finaliseExternalTables,
|
finaliseExternalTables,
|
||||||
checkExternalTables,
|
checkExternalTables,
|
||||||
|
HOST_ADDRESS,
|
||||||
} from "./utils"
|
} from "./utils"
|
||||||
import dayjs from "dayjs"
|
import dayjs from "dayjs"
|
||||||
import { NUMBER_REGEX } from "../utilities"
|
import { NUMBER_REGEX } from "../utilities"
|
||||||
|
@ -49,7 +50,7 @@ const SCHEMA: Integration = {
|
||||||
datasource: {
|
datasource: {
|
||||||
host: {
|
host: {
|
||||||
type: DatasourceFieldType.STRING,
|
type: DatasourceFieldType.STRING,
|
||||||
default: "localhost",
|
default: HOST_ADDRESS,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
port: {
|
port: {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import {
|
||||||
finaliseExternalTables,
|
finaliseExternalTables,
|
||||||
getSqlQuery,
|
getSqlQuery,
|
||||||
SqlClient,
|
SqlClient,
|
||||||
|
HOST_ADDRESS,
|
||||||
} from "./utils"
|
} from "./utils"
|
||||||
import Sql from "./base/sql"
|
import Sql from "./base/sql"
|
||||||
import {
|
import {
|
||||||
|
@ -63,7 +64,7 @@ const SCHEMA: Integration = {
|
||||||
datasource: {
|
datasource: {
|
||||||
host: {
|
host: {
|
||||||
type: DatasourceFieldType.STRING,
|
type: DatasourceFieldType.STRING,
|
||||||
default: "localhost",
|
default: HOST_ADDRESS,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
port: {
|
port: {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
finaliseExternalTables,
|
finaliseExternalTables,
|
||||||
SqlClient,
|
SqlClient,
|
||||||
checkExternalTables,
|
checkExternalTables,
|
||||||
|
HOST_ADDRESS,
|
||||||
} from "./utils"
|
} from "./utils"
|
||||||
import Sql from "./base/sql"
|
import Sql from "./base/sql"
|
||||||
import { PostgresColumn } from "./base/types"
|
import { PostgresColumn } from "./base/types"
|
||||||
|
@ -72,7 +73,7 @@ const SCHEMA: Integration = {
|
||||||
datasource: {
|
datasource: {
|
||||||
host: {
|
host: {
|
||||||
type: DatasourceFieldType.STRING,
|
type: DatasourceFieldType.STRING,
|
||||||
default: "localhost",
|
default: HOST_ADDRESS,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
port: {
|
port: {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
QueryType,
|
QueryType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import Redis from "ioredis"
|
import Redis from "ioredis"
|
||||||
|
import { HOST_ADDRESS } from "./utils"
|
||||||
|
|
||||||
interface RedisConfig {
|
interface RedisConfig {
|
||||||
host: string
|
host: string
|
||||||
|
@ -28,7 +29,7 @@ const SCHEMA: Integration = {
|
||||||
host: {
|
host: {
|
||||||
type: DatasourceFieldType.STRING,
|
type: DatasourceFieldType.STRING,
|
||||||
required: true,
|
required: true,
|
||||||
default: "localhost",
|
default: HOST_ADDRESS,
|
||||||
},
|
},
|
||||||
port: {
|
port: {
|
||||||
type: DatasourceFieldType.NUMBER,
|
type: DatasourceFieldType.NUMBER,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
DEFAULT_BB_DATASOURCE_ID,
|
DEFAULT_BB_DATASOURCE_ID,
|
||||||
} from "../constants"
|
} from "../constants"
|
||||||
import { helpers } from "@budibase/shared-core"
|
import { helpers } from "@budibase/shared-core"
|
||||||
|
import env from "../environment"
|
||||||
|
|
||||||
const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}`
|
const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}`
|
||||||
const ROW_ID_REGEX = /^\[.*]$/g
|
const ROW_ID_REGEX = /^\[.*]$/g
|
||||||
|
@ -92,6 +93,14 @@ export enum SqlClient {
|
||||||
ORACLE = "oracledb",
|
ORACLE = "oracledb",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isCloud = env.isProd() && !env.SELF_HOSTED
|
||||||
|
const isSelfHost = env.isProd() && env.SELF_HOSTED
|
||||||
|
export const HOST_ADDRESS = isSelfHost
|
||||||
|
? "host.docker.internal"
|
||||||
|
: isCloud
|
||||||
|
? ""
|
||||||
|
: "localhost"
|
||||||
|
|
||||||
export function isExternalTableID(tableId: string) {
|
export function isExternalTableID(tableId: string) {
|
||||||
return tableId.includes(DocumentType.DATASOURCE)
|
return tableId.includes(DocumentType.DATASOURCE)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,12 @@ const config = (format, outputFile) => ({
|
||||||
format,
|
format,
|
||||||
file: outputFile,
|
file: outputFile,
|
||||||
},
|
},
|
||||||
|
onwarn(warning, warn) {
|
||||||
|
if (warning.code === "EVAL") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
warn(warning)
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
typescript(),
|
typescript(),
|
||||||
resolve({
|
resolve({
|
||||||
|
|
|
@ -68,6 +68,11 @@ export interface CreateAdminUserRequest {
|
||||||
ssoId?: string
|
ssoId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AddSSoUserRequest {
|
||||||
|
ssoId: string
|
||||||
|
email: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface CreateAdminUserResponse {
|
export interface CreateAdminUserResponse {
|
||||||
_id: string
|
_id: string
|
||||||
_rev: string
|
_rev: string
|
||||||
|
|
|
@ -3,6 +3,7 @@ import env from "../../../environment"
|
||||||
import {
|
import {
|
||||||
AcceptUserInviteRequest,
|
AcceptUserInviteRequest,
|
||||||
AcceptUserInviteResponse,
|
AcceptUserInviteResponse,
|
||||||
|
AddSSoUserRequest,
|
||||||
BulkUserRequest,
|
BulkUserRequest,
|
||||||
BulkUserResponse,
|
BulkUserResponse,
|
||||||
CloudAccount,
|
CloudAccount,
|
||||||
|
@ -15,6 +16,7 @@ import {
|
||||||
LockName,
|
LockName,
|
||||||
LockType,
|
LockType,
|
||||||
MigrationType,
|
MigrationType,
|
||||||
|
PlatformUserByEmail,
|
||||||
SaveUserResponse,
|
SaveUserResponse,
|
||||||
SearchUsersRequest,
|
SearchUsersRequest,
|
||||||
User,
|
User,
|
||||||
|
@ -53,6 +55,25 @@ export const save = async (ctx: UserCtx<User, SaveUserResponse>) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const addSsoSupport = async (ctx: Ctx<AddSSoUserRequest>) => {
|
||||||
|
const { email, ssoId } = ctx.request.body
|
||||||
|
try {
|
||||||
|
// Status is changed to 404 from getUserDoc if user is not found
|
||||||
|
let userByEmail = (await platform.users.getUserDoc(
|
||||||
|
email
|
||||||
|
)) as PlatformUserByEmail
|
||||||
|
await platform.users.addSsoUser(
|
||||||
|
ssoId,
|
||||||
|
email,
|
||||||
|
userByEmail.userId,
|
||||||
|
userByEmail.tenantId
|
||||||
|
)
|
||||||
|
ctx.status = 200
|
||||||
|
} catch (err: any) {
|
||||||
|
ctx.throw(err.status || 400, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const bulkDelete = async (userIds: string[], currentUserId: string) => {
|
const bulkDelete = async (userIds: string[], currentUserId: string) => {
|
||||||
if (userIds?.indexOf(currentUserId) !== -1) {
|
if (userIds?.indexOf(currentUserId) !== -1) {
|
||||||
throw new Error("Unable to delete self.")
|
throw new Error("Unable to delete self.")
|
||||||
|
|
|
@ -41,6 +41,10 @@ const PUBLIC_ENDPOINTS = [
|
||||||
route: "/api/global/users/init",
|
route: "/api/global/users/init",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
route: "/api/global/users/sso",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
route: "/api/global/users/invite/accept",
|
route: "/api/global/users/invite/accept",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -81,6 +85,11 @@ const NO_TENANCY_ENDPOINTS = [
|
||||||
route: "/api/global/users/init",
|
route: "/api/global/users/init",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
|
// tenant is retrieved from the user found by the requested email
|
||||||
|
{
|
||||||
|
route: "/api/global/users/sso",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
// deprecated single tenant sso callback
|
// deprecated single tenant sso callback
|
||||||
{
|
{
|
||||||
route: "/api/admin/auth/google/callback",
|
route: "/api/admin/auth/google/callback",
|
||||||
|
|
|
@ -520,10 +520,51 @@ describe("/api/global/users", () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createPasswordUser() {
|
||||||
|
return config.doInTenant(() => {
|
||||||
|
const user = structures.users.user()
|
||||||
|
return userSdk.db.save(user)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
it("should be able to update an sso user that has no password", async () => {
|
it("should be able to update an sso user that has no password", async () => {
|
||||||
const user = await createSSOUser()
|
const user = await createSSOUser()
|
||||||
await config.api.users.saveUser(user)
|
await config.api.users.saveUser(user)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("sso support couldn't be used by admin. It is cloud restricted and needs internal key", async () => {
|
||||||
|
const user = await config.createUser()
|
||||||
|
const ssoId = "fake-ssoId"
|
||||||
|
await config.api.users
|
||||||
|
.addSsoSupportDefaultAuth(ssoId, user.email)
|
||||||
|
.expect("Content-Type", /json/)
|
||||||
|
.expect(403)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("if user email doesn't exist, SSO support couldn't be added. Not found error returned", async () => {
|
||||||
|
const ssoId = "fake-ssoId"
|
||||||
|
const email = "fake-email@budibase.com"
|
||||||
|
await config.api.users
|
||||||
|
.addSsoSupportInternalAPIAuth(ssoId, email)
|
||||||
|
.expect("Content-Type", /json/)
|
||||||
|
.expect(404)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("if user email exist, SSO support is added", async () => {
|
||||||
|
const user = await createPasswordUser()
|
||||||
|
const ssoId = "fakessoId"
|
||||||
|
await config.api.users
|
||||||
|
.addSsoSupportInternalAPIAuth(ssoId, user.email)
|
||||||
|
.expect(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("if user ssoId is already assigned, no change will be applied", async () => {
|
||||||
|
const user = await createSSOUser()
|
||||||
|
user.ssoId = "testssoId"
|
||||||
|
await config.api.users
|
||||||
|
.addSsoSupportInternalAPIAuth(user.ssoId, user.email)
|
||||||
|
.expect(200)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,12 @@ router
|
||||||
users.buildUserSaveValidation(),
|
users.buildUserSaveValidation(),
|
||||||
controller.save
|
controller.save
|
||||||
)
|
)
|
||||||
|
.post(
|
||||||
|
"/api/global/users/sso",
|
||||||
|
cloudRestricted,
|
||||||
|
users.buildAddSsoSupport(),
|
||||||
|
controller.addSsoSupport
|
||||||
|
)
|
||||||
.post(
|
.post(
|
||||||
"/api/global/users/bulk",
|
"/api/global/users/bulk",
|
||||||
auth.adminOnly,
|
auth.adminOnly,
|
||||||
|
|
|
@ -41,6 +41,15 @@ export const buildUserSaveValidation = () => {
|
||||||
return auth.joiValidator.body(Joi.object(schema).required().unknown(true))
|
return auth.joiValidator.body(Joi.object(schema).required().unknown(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const buildAddSsoSupport = () => {
|
||||||
|
return auth.joiValidator.body(
|
||||||
|
Joi.object({
|
||||||
|
ssoId: Joi.string().required(),
|
||||||
|
email: Joi.string().required(),
|
||||||
|
}).required()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export const buildUserBulkUserValidation = (isSelf = false) => {
|
export const buildUserBulkUserValidation = (isSelf = false) => {
|
||||||
if (!isSelf) {
|
if (!isSelf) {
|
||||||
schema = {
|
schema = {
|
||||||
|
|
|
@ -127,6 +127,20 @@ export class UserAPI extends TestAPI {
|
||||||
.expect(status ? status : 200)
|
.expect(status ? status : 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addSsoSupportInternalAPIAuth = (ssoId: string, email: string) => {
|
||||||
|
return this.request
|
||||||
|
.post(`/api/global/users/sso`)
|
||||||
|
.send({ ssoId, email })
|
||||||
|
.set(this.config.internalAPIHeaders())
|
||||||
|
}
|
||||||
|
|
||||||
|
addSsoSupportDefaultAuth = (ssoId: string, email: string) => {
|
||||||
|
return this.request
|
||||||
|
.post(`/api/global/users/sso`)
|
||||||
|
.send({ ssoId, email })
|
||||||
|
.set(this.config.defaultHeaders())
|
||||||
|
}
|
||||||
|
|
||||||
deleteUser = (userId: string, status?: number) => {
|
deleteUser = (userId: string, status?: number) => {
|
||||||
return this.request
|
return this.request
|
||||||
.delete(`/api/global/users/${userId}`)
|
.delete(`/api/global/users/${userId}`)
|
||||||
|
|
Loading…
Reference in New Issue