Further work towards the re-implementation of auth, changing how the appId is determined, now it mainly will use a header, and a cookie which will be written to store the current status of appId.
This commit is contained in:
parent
871e9b123e
commit
ac73b5c4aa
|
@ -1,15 +1,17 @@
|
||||||
|
import { store } from "./index"
|
||||||
|
import { get as svelteGet } from "svelte/store"
|
||||||
|
|
||||||
const apiCall = method => async (
|
const apiCall = method => async (
|
||||||
url,
|
url,
|
||||||
body,
|
body,
|
||||||
headers = { "Content-Type": "application/json" }
|
headers = { "Content-Type": "application/json" }
|
||||||
) => {
|
) => {
|
||||||
const response = await fetch(url, {
|
headers["x-budibase-app-id"] = svelteGet(store).appId
|
||||||
|
return await fetch(url, {
|
||||||
method: method,
|
method: method,
|
||||||
body: body && JSON.stringify(body),
|
body: body && JSON.stringify(body),
|
||||||
headers,
|
headers,
|
||||||
})
|
})
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const post = apiCall("POST")
|
export const post = apiCall("POST")
|
||||||
|
|
|
@ -84,8 +84,6 @@
|
||||||
<Button
|
<Button
|
||||||
secondary
|
secondary
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
// reset cookies for this app
|
|
||||||
document.cookie = `budibase:${application}:local=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;`
|
|
||||||
window.open(`/${application}`)
|
window.open(`/${application}`)
|
||||||
}}>
|
}}>
|
||||||
Preview
|
Preview
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { authenticate } from "./authenticate"
|
import {authenticate} from "./authenticate"
|
||||||
// import appStore from "../state/store"
|
import {getAppIdFromPath} from "../render/getAppId";
|
||||||
|
|
||||||
const apiCall = method => async ({ url, body }) => {
|
const apiCall = method => async ({ url, body }) => {
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: method,
|
method: method,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
"x-budibase-app-id": getAppIdFromPath(),
|
||||||
},
|
},
|
||||||
body: body && JSON.stringify(body),
|
body: body && JSON.stringify(body),
|
||||||
credentials: "same-origin",
|
credentials: "same-origin",
|
||||||
|
@ -36,9 +37,8 @@ const del = apiCall("DELETE")
|
||||||
|
|
||||||
const ERROR_MEMBER = "##error"
|
const ERROR_MEMBER = "##error"
|
||||||
const error = message => {
|
const error = message => {
|
||||||
const err = { [ERROR_MEMBER]: message }
|
|
||||||
// appStore.update(s => s["##error_message"], message)
|
// appStore.update(s => s["##error_message"], message)
|
||||||
return err
|
return {[ERROR_MEMBER]: message}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSuccess = obj => !obj || !obj[ERROR_MEMBER]
|
const isSuccess = obj => !obj || !obj[ERROR_MEMBER]
|
||||||
|
@ -81,6 +81,9 @@ const makeRowRequestBody = (parameters, state) => {
|
||||||
|
|
||||||
// then override with supplied parameters
|
// then override with supplied parameters
|
||||||
for (let fieldName in parameters.fields) {
|
for (let fieldName in parameters.fields) {
|
||||||
|
if (!parameters.fields.hasOwnProperty(fieldName)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
const field = parameters.fields[fieldName]
|
const field = parameters.fields[fieldName]
|
||||||
|
|
||||||
// ensure fields sent are of the correct type
|
// ensure fields sent are of the correct type
|
||||||
|
|
|
@ -4,10 +4,10 @@ const bcrypt = require("../../utilities/bcrypt")
|
||||||
const env = require("../../environment")
|
const env = require("../../environment")
|
||||||
const { getAPIKey } = require("../../utilities/usageQuota")
|
const { getAPIKey } = require("../../utilities/usageQuota")
|
||||||
const { generateUserID } = require("../../db/utils")
|
const { generateUserID } = require("../../db/utils")
|
||||||
const { getCookieName } = require("../../utilities")
|
const { setCookie } = require("../../utilities")
|
||||||
|
|
||||||
exports.authenticate = async ctx => {
|
exports.authenticate = async ctx => {
|
||||||
const appId = ctx.user.appId
|
const appId = ctx.appId
|
||||||
if (!appId) ctx.throw(400, "No appId")
|
if (!appId) ctx.throw(400, "No appId")
|
||||||
|
|
||||||
const { username, password } = ctx.request.body
|
const { username, password } = ctx.request.body
|
||||||
|
@ -46,15 +46,7 @@ exports.authenticate = async ctx => {
|
||||||
expiresIn: "1 day",
|
expiresIn: "1 day",
|
||||||
})
|
})
|
||||||
|
|
||||||
const expires = new Date()
|
setCookie(ctx, appId, token)
|
||||||
expires.setDate(expires.getDate() + 1)
|
|
||||||
|
|
||||||
ctx.cookies.set(getCookieName(appId), token, {
|
|
||||||
expires,
|
|
||||||
path: "/",
|
|
||||||
httpOnly: false,
|
|
||||||
overwrite: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
delete dbUser.password
|
delete dbUser.password
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
|
|
|
@ -9,7 +9,7 @@ const {
|
||||||
} = require("../utilities/accessLevels")
|
} = require("../utilities/accessLevels")
|
||||||
const env = require("../environment")
|
const env = require("../environment")
|
||||||
const { AuthTypes } = require("../constants")
|
const { AuthTypes } = require("../constants")
|
||||||
const { getAppId, getCookieName } = require("../utilities")
|
const { getAppId, getCookieName, setCookie } = require("../utilities")
|
||||||
|
|
||||||
module.exports = async (ctx, next) => {
|
module.exports = async (ctx, next) => {
|
||||||
if (ctx.path === "/_builder") {
|
if (ctx.path === "/_builder") {
|
||||||
|
@ -17,7 +17,14 @@ module.exports = async (ctx, next) => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const appId = getAppId(ctx)
|
// do everything we can to make sure the appId is held correctly
|
||||||
|
// we hold it in state as a
|
||||||
|
let appId = getAppId(ctx)
|
||||||
|
if (appId) {
|
||||||
|
setCookie(ctx, "currentapp", appId)
|
||||||
|
} else {
|
||||||
|
appId = ctx.cookies.get(getCookieName("currentapp"))
|
||||||
|
}
|
||||||
|
|
||||||
const appToken = ctx.cookies.get(getCookieName(appId))
|
const appToken = ctx.cookies.get(getCookieName(appId))
|
||||||
const builderToken = ctx.cookies.get(getCookieName())
|
const builderToken = ctx.cookies.get(getCookieName())
|
||||||
|
@ -43,14 +50,12 @@ module.exports = async (ctx, next) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const jwtPayload = jwt.verify(token, ctx.config.jwtSecret)
|
const jwtPayload = jwt.verify(token, ctx.config.jwtSecret)
|
||||||
|
ctx.appId = appId
|
||||||
ctx.auth.apiKey = jwtPayload.apiKey
|
ctx.auth.apiKey = jwtPayload.apiKey
|
||||||
ctx.user = {
|
ctx.user = {
|
||||||
...jwtPayload,
|
...jwtPayload,
|
||||||
appId: jwtPayload.appId,
|
appId: appId,
|
||||||
accessLevel: await getAccessLevel(
|
accessLevel: await getAccessLevel(appId, jwtPayload.accessLevelId),
|
||||||
jwtPayload.appId,
|
|
||||||
jwtPayload.accessLevelId
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.throw(err.status || STATUS_CODES.FORBIDDEN, err.text)
|
ctx.throw(err.status || STATUS_CODES.FORBIDDEN, err.text)
|
||||||
|
|
|
@ -3,7 +3,7 @@ const env = require("../../environment")
|
||||||
const CouchDB = require("../../db")
|
const CouchDB = require("../../db")
|
||||||
const jwt = require("jsonwebtoken")
|
const jwt = require("jsonwebtoken")
|
||||||
const { DocumentTypes, SEPARATOR } = require("../../db/utils")
|
const { DocumentTypes, SEPARATOR } = require("../../db/utils")
|
||||||
const { getCookieName } = require("../index")
|
const { setCookie } = require("../index")
|
||||||
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
|
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
|
||||||
|
|
||||||
module.exports = async (ctx, appId, version) => {
|
module.exports = async (ctx, appId, version) => {
|
||||||
|
@ -20,21 +20,13 @@ module.exports = async (ctx, appId, version) => {
|
||||||
expiresIn: "30 days",
|
expiresIn: "30 days",
|
||||||
})
|
})
|
||||||
|
|
||||||
const expiry = new Date()
|
|
||||||
expiry.setDate(expiry.getDate() + 30)
|
|
||||||
// set the builder token
|
// set the builder token
|
||||||
ctx.cookies.set(getCookieName(), token, {
|
setCookie(ctx, "builder", token)
|
||||||
expires: expiry,
|
|
||||||
httpOnly: false,
|
|
||||||
overwrite: true,
|
|
||||||
})
|
|
||||||
// need to clear all app tokens or else unable to use the app in the builder
|
// need to clear all app tokens or else unable to use the app in the builder
|
||||||
let allDbNames = await CouchDB.allDbs()
|
let allDbNames = await CouchDB.allDbs()
|
||||||
allDbNames.map(dbName => {
|
allDbNames.map(dbName => {
|
||||||
if (dbName.startsWith(APP_PREFIX)) {
|
if (dbName.startsWith(APP_PREFIX)) {
|
||||||
ctx.cookies.set(getCookieName(dbName), "", {
|
setCookie(ctx, dbName, "")
|
||||||
overwrite: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
const env = require("../environment")
|
const env = require("../environment")
|
||||||
|
const { DocumentTypes, SEPARATOR } = require("../db/utils")
|
||||||
|
|
||||||
|
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
|
||||||
|
|
||||||
exports.wait = ms => new Promise(resolve => setTimeout(resolve, ms))
|
exports.wait = ms => new Promise(resolve => setTimeout(resolve, ms))
|
||||||
|
|
||||||
|
@ -17,26 +20,47 @@ exports.isDev = () => {
|
||||||
* @returns {string|undefined} If an appId was found it will be returned.
|
* @returns {string|undefined} If an appId was found it will be returned.
|
||||||
*/
|
*/
|
||||||
exports.getAppId = ctx => {
|
exports.getAppId = ctx => {
|
||||||
let appId = env.CLOUD ? ctx.subdomains[1] : ctx.params.appId
|
let appId = ctx.headers["x-budibase-app-id"]
|
||||||
|
if (!appId) {
|
||||||
|
appId = env.CLOUD ? ctx.subdomains[1] : ctx.params.appId
|
||||||
|
}
|
||||||
// look in body if can't find it in subdomain
|
// look in body if can't find it in subdomain
|
||||||
if (!appId && ctx.request.body && ctx.request.body.appId) {
|
if (!appId && ctx.request.body && ctx.request.body.appId) {
|
||||||
appId = ctx.request.body.appId
|
appId = ctx.request.body.appId
|
||||||
}
|
}
|
||||||
// if appId can't be determined from path param or subdomain
|
let appPath =
|
||||||
if (!appId && ctx.request.headers.referer) {
|
ctx.request.headers.referrer ||
|
||||||
const url = new URL(ctx.request.headers.referer)
|
ctx.path.split("/").filter(subPath => subPath.startsWith(APP_PREFIX))
|
||||||
// remove leading and trailing slashes from appId
|
if (!appId && appPath.length !== 0) {
|
||||||
appId = url.pathname.replace(/\//g, "")
|
appId = appPath[0]
|
||||||
}
|
}
|
||||||
return appId
|
return appId
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of the cookie which is to be updated/retrieved
|
* Get the name of the cookie which is to be updated/retrieved
|
||||||
* @param {string|undefined|null} appId OPTIONAL can specify the specific app if previewing etc
|
* @param {string|undefined|null} name OPTIONAL can specify the specific app if previewing etc
|
||||||
* @returns {string} The name of the token trying to find
|
* @returns {string} The name of the token trying to find
|
||||||
*/
|
*/
|
||||||
exports.getCookieName = (appId = null) => {
|
exports.getCookieName = (name = "builder") => {
|
||||||
let environment = env.CLOUD ? "cloud" : "local"
|
let environment = env.CLOUD ? "cloud" : "local"
|
||||||
return `budibase:${appId ? appId : "builder"}:${environment}`
|
return `budibase:${name}:${environment}`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a cookie for the request, has a hardcoded expiry.
|
||||||
|
* @param {object} ctx The request which is to be manipulated.
|
||||||
|
* @param {string} name The name of the cookie to set.
|
||||||
|
* @param {string|object} value The value of cookie which will be set.
|
||||||
|
*/
|
||||||
|
exports.setCookie = (ctx, name, value) => {
|
||||||
|
const expires = new Date()
|
||||||
|
expires.setDate(expires.getDate() + 1)
|
||||||
|
|
||||||
|
ctx.cookies.set(exports.getCookieName(name), value, {
|
||||||
|
expires,
|
||||||
|
path: "/",
|
||||||
|
httpOnly: false,
|
||||||
|
overwrite: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,10 @@ const apiCall = method => async (
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
|
const appId = location.pathname.split("/")[1]
|
||||||
|
if (appId) {
|
||||||
|
headers["x-budibase-app-id"] = appId
|
||||||
|
}
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: method,
|
method: method,
|
||||||
body: body && JSON.stringify(body),
|
body: body && JSON.stringify(body),
|
||||||
|
|
Loading…
Reference in New Issue