Skip to content

Commit

Permalink
Merge pull request #10927 from Budibase/revert-merge-develop-1
Browse files Browse the repository at this point in the history
Revert "Merge branch 'develop' into master"
  • Loading branch information
Rory-Powell committed Jun 16, 2023
2 parents 13d5248 + f3678ef commit d530a17
Show file tree
Hide file tree
Showing 76 changed files with 1,415 additions and 2,492 deletions.
1 change: 1 addition & 0 deletions lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"packages/worker",
"packages/pro/packages/pro"
],
"useWorkspaces": true,
"command": {
"publish": {
"ignoreChanges": [
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
"husky": "^8.0.3",
"js-yaml": "^4.1.0",
"kill-port": "^1.6.1",
"lerna": "^7.0.1",
"lerna": "7.0.0-alpha.0",
"madge": "^6.0.0",
"minimist": "^1.2.8",
"nx": "^16.3.2",
"nx": "^16.2.1",
"prettier": "^2.3.1",
"prettier-plugin-svelte": "^2.3.0",
"rimraf": "^3.0.2",
Expand Down
46 changes: 26 additions & 20 deletions packages/backend-core/src/middleware/passport/datasource/google.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import * as google from "../sso/google"
import { Cookie } from "../../../constants"
import { clearCookie, getCookie } from "../../../utils"
import { doWithDB } from "../../../db"
import * as configs from "../../../configs"
import * as cache from "../../../cache"
import * as utils from "../../../utils"
import { UserCtx, SSOProfile } from "@budibase/types"
import { BBContext, Database, SSOProfile } from "@budibase/types"
import { ssoSaveUserNoOp } from "../sso/sso"

const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy

type Passport = {
Expand All @@ -23,7 +22,7 @@ async function fetchGoogleCreds() {

export async function preAuth(
passport: Passport,
ctx: UserCtx,
ctx: BBContext,
next: Function
) {
// get the relevant config
Expand All @@ -37,8 +36,8 @@ export async function preAuth(
ssoSaveUserNoOp
)

if (!ctx.query.appId) {
ctx.throw(400, "appId query param not present.")
if (!ctx.query.appId || !ctx.query.datasourceId) {
ctx.throw(400, "appId and datasourceId query params not present.")
}

return passport.authenticate(strategy, {
Expand All @@ -50,15 +49,15 @@ export async function preAuth(

export async function postAuth(
passport: Passport,
ctx: UserCtx,
ctx: BBContext,
next: Function
) {
// get the relevant config
const config = await fetchGoogleCreds()
const platformUrl = await configs.getPlatformUrl({ tenantAware: false })

let callbackUrl = `${platformUrl}/api/global/auth/datasource/google/callback`
const authStateCookie = utils.getCookie(ctx, Cookie.DatasourceAuth)
const authStateCookie = getCookie(ctx, Cookie.DatasourceAuth)

return passport.authenticate(
new GoogleStrategy(
Expand All @@ -70,26 +69,33 @@ export async function postAuth(
(
accessToken: string,
refreshToken: string,
_profile: SSOProfile,
profile: SSOProfile,
done: Function
) => {
utils.clearCookie(ctx, Cookie.DatasourceAuth)
clearCookie(ctx, Cookie.DatasourceAuth)
done(null, { accessToken, refreshToken })
}
),
{ successRedirect: "/", failureRedirect: "/error" },
async (err: any, tokens: string[]) => {
const baseUrl = `/builder/app/${authStateCookie.appId}/data`

const id = utils.newid()
await cache.store(
`datasource:creation:${authStateCookie.appId}:google:${id}`,
{
tokens,
// update the DB for the datasource with all the user info
await doWithDB(authStateCookie.appId, async (db: Database) => {
let datasource
try {
datasource = await db.get(authStateCookie.datasourceId)
} catch (err: any) {
if (err.status === 404) {
ctx.redirect(baseUrl)
}
}
)

ctx.redirect(`${baseUrl}/new?continue_google_setup=${id}`)
if (!datasource.config) {
datasource.config = {}
}
datasource.config.auth = { type: "google", ...tokens }
await db.put(datasource)
ctx.redirect(`${baseUrl}/datasource/${authStateCookie.datasourceId}`)
})
}
)(ctx, next)
}
125 changes: 4 additions & 121 deletions packages/backend-core/src/security/encryption.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import crypto from "crypto"
import fs from "fs"
import zlib from "zlib"
import env from "../environment"
import { join } from "path"

const ALGO = "aes-256-ctr"
const SEPARATOR = "-"
const ITERATIONS = 10000
const RANDOM_BYTES = 16
const STRETCH_LENGTH = 32

const SALT_LENGTH = 16
const IV_LENGTH = 16

export enum SecretOption {
API = "api",
ENCRYPTION = "encryption",
Expand All @@ -36,15 +31,15 @@ export function getSecret(secretOption: SecretOption): string {
return secret
}

function stretchString(secret: string, salt: Buffer) {
return crypto.pbkdf2Sync(secret, salt, ITERATIONS, STRETCH_LENGTH, "sha512")
function stretchString(string: string, salt: Buffer) {
return crypto.pbkdf2Sync(string, salt, ITERATIONS, STRETCH_LENGTH, "sha512")
}

export function encrypt(
input: string,
secretOption: SecretOption = SecretOption.API
) {
const salt = crypto.randomBytes(SALT_LENGTH)
const salt = crypto.randomBytes(RANDOM_BYTES)
const stretched = stretchString(getSecret(secretOption), salt)
const cipher = crypto.createCipheriv(ALGO, stretched, salt)
const base = cipher.update(input)
Expand All @@ -65,115 +60,3 @@ export function decrypt(
const final = decipher.final()
return Buffer.concat([base, final]).toString()
}

export async function encryptFile(
{ dir, filename }: { dir: string; filename: string },
secret: string
) {
const outputFileName = `${filename}.enc`

const filePath = join(dir, filename)
const inputFile = fs.createReadStream(filePath)
const outputFile = fs.createWriteStream(join(dir, outputFileName))

const salt = crypto.randomBytes(SALT_LENGTH)
const iv = crypto.randomBytes(IV_LENGTH)
const stretched = stretchString(secret, salt)
const cipher = crypto.createCipheriv(ALGO, stretched, iv)

outputFile.write(salt)
outputFile.write(iv)

inputFile.pipe(zlib.createGzip()).pipe(cipher).pipe(outputFile)

return new Promise<{ filename: string; dir: string }>(r => {
outputFile.on("finish", () => {
r({
filename: outputFileName,
dir,
})
})
})
}

async function getSaltAndIV(path: string) {
const fileStream = fs.createReadStream(path)

const salt = await readBytes(fileStream, SALT_LENGTH)
const iv = await readBytes(fileStream, IV_LENGTH)
fileStream.close()
return { salt, iv }
}

export async function decryptFile(
inputPath: string,
outputPath: string,
secret: string
) {
const { salt, iv } = await getSaltAndIV(inputPath)
const inputFile = fs.createReadStream(inputPath, {
start: SALT_LENGTH + IV_LENGTH,
})

const outputFile = fs.createWriteStream(outputPath)

const stretched = stretchString(secret, salt)
const decipher = crypto.createDecipheriv(ALGO, stretched, iv)

const unzip = zlib.createGunzip()

inputFile.pipe(decipher).pipe(unzip).pipe(outputFile)

return new Promise<void>((res, rej) => {
outputFile.on("finish", () => {
outputFile.close()
res()
})

inputFile.on("error", e => {
outputFile.close()
rej(e)
})

decipher.on("error", e => {
outputFile.close()
rej(e)
})

unzip.on("error", e => {
outputFile.close()
rej(e)
})

outputFile.on("error", e => {
outputFile.close()
rej(e)
})
})
}

function readBytes(stream: fs.ReadStream, length: number) {
return new Promise<Buffer>((resolve, reject) => {
let bytesRead = 0
const data: Buffer[] = []

stream.on("readable", () => {
let chunk

while ((chunk = stream.read(length - bytesRead)) !== null) {
data.push(chunk)
bytesRead += chunk.length
}

resolve(Buffer.concat(data))
})

stream.on("end", () => {
reject(new Error("Insufficient data in the stream."))
})

stream.on("error", error => {
reject(error)
})
})
}
9 changes: 1 addition & 8 deletions packages/backend-core/src/security/roles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,9 @@ export function lowerBuiltinRoleID(roleId1?: string, roleId2?: string): string {
* Gets the role object, this is mainly useful for two purposes, to check if the level exists and
* to check if the role inherits any others.
* @param {string|null} roleId The level ID to lookup.
* @param {object|null} opts options for the function, like whether to halt errors, instead return public.
* @returns {Promise<Role|object|null>} The role object, which may contain an "inherits" property.
*/
export async function getRole(
roleId?: string,
opts?: { defaultPublic?: boolean }
): Promise<RoleDoc | undefined> {
export async function getRole(roleId?: string): Promise<RoleDoc | undefined> {
if (!roleId) {
return undefined
}
Expand All @@ -165,9 +161,6 @@ export async function getRole(
// finalise the ID
role._id = getExternalRoleID(role._id)
} catch (err) {
if (!isBuiltin(roleId) && opts?.defaultPublic) {
return cloneDeep(BUILTIN_ROLES.PUBLIC)
}
// only throw an error if there is no role at all
if (Object.keys(role).length === 0) {
throw err
Expand Down
20 changes: 3 additions & 17 deletions packages/bbui/src/FancyForm/FancyCheckbox.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
export let disabled = false
export let error = null
export let validate = null
export let indeterminate = false
export let compact = false
const dispatch = createEventDispatcher()
Expand All @@ -23,19 +21,11 @@
}
</script>

<FancyField
{error}
{value}
{validate}
{disabled}
{compact}
clickable
on:click={onChange}
>
<FancyField {error} {value} {validate} {disabled} clickable on:click={onChange}>
<span>
<Checkbox {disabled} {value} {indeterminate} />
<Checkbox {disabled} {value} />
</span>
<div class="text" class:compact>
<div class="text">
{#if text}
{text}
{/if}
Expand All @@ -57,10 +47,6 @@
line-clamp: 2;
-webkit-box-orient: vertical;
}
.text.compact {
font-size: 13px;
line-height: 15px;
}
.text > :global(*) {
font-size: inherit !important;
}
Expand Down
Loading

0 comments on commit d530a17

Please sign in to comment.