Merge branch 'master' into feature/add-grid-to-standard-components
This commit is contained in:
commit
28caf55ac4
|
@ -90,6 +90,8 @@ const contextToBindables = (models, walkResult) => context => {
|
|||
runtimeBinding: `${contextParentPath}data.${key}`,
|
||||
// how the binding exressions looks to the user of the builder
|
||||
readableBinding: `${context.instance._instanceName}.${model.name}.${key}`,
|
||||
// model / view info
|
||||
model: context.model,
|
||||
})
|
||||
|
||||
// see ModelViewSelect.svelte for the format of context.model
|
||||
|
|
|
@ -36,7 +36,8 @@ export const saveCurrentPreviewItem = s =>
|
|||
: saveScreenApi(s.currentPreviewItem, s)
|
||||
|
||||
export const savePage = async s => {
|
||||
const page = s.pages[s.currentPageName]
|
||||
const pageName = s.currentPageName || "main"
|
||||
const page = s.pages[pageName]
|
||||
await api.post(`/_builder/api/${s.appId}/pages/${s.currentPageName}`, {
|
||||
page: { componentLibraries: s.pages.componentLibraries, ...page },
|
||||
uiFunctions: s.currentPageFunctions,
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
}
|
||||
|
||||
function fieldOptions(field) {
|
||||
return viewModel.schema[field].type === "string"
|
||||
return viewModel.schema[field].type === "options"
|
||||
? viewModel.schema[field].constraints.inclusion
|
||||
: [true, false]
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
.map(template => template.create())
|
||||
|
||||
for (let screen of screens) {
|
||||
console.log(JSON.stringify(screen))
|
||||
try {
|
||||
await store.createScreen(screen)
|
||||
} catch (_) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import { Input } from "@budibase/bbui"
|
||||
import { Input, Label } from "@budibase/bbui"
|
||||
import api from "builderStore/api"
|
||||
import { backendUiStore } from "builderStore"
|
||||
import analytics from "analytics"
|
||||
|
||||
let keys = { budibase: "" }
|
||||
|
@ -38,6 +39,10 @@
|
|||
edit
|
||||
value={keys.budibase}
|
||||
label="Budibase API Key" />
|
||||
<div>
|
||||
<Label extraSmall grey>Instance ID (Webhooks)</Label>
|
||||
<span>{$backendUiStore.selectedDatabase._id}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
@ -45,4 +50,9 @@
|
|||
display: grid;
|
||||
grid-gap: var(--spacing-xl);
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: var(--font-size-xs);
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import { Input, Button, Spacer, Select, ModalContent } from "@budibase/bbui"
|
||||
import getTemplates from "builderStore/store/screenTemplates"
|
||||
import { some } from "lodash/fp"
|
||||
import analytics from "analytics"
|
||||
|
||||
const CONTAINER = "@budibase/standard-components/container"
|
||||
|
||||
|
@ -29,7 +30,7 @@
|
|||
|
||||
const templateChanged = newTemplateIndex => {
|
||||
if (newTemplateIndex === undefined) return
|
||||
|
||||
const template = templates[newTemplateIndex]
|
||||
draftScreen = templates[newTemplateIndex].create()
|
||||
if (draftScreen.props._instanceName) {
|
||||
name = draftScreen.props._instanceName
|
||||
|
@ -63,6 +64,13 @@
|
|||
|
||||
store.createScreen(draftScreen)
|
||||
|
||||
if (templateIndex !== undefined) {
|
||||
const template = templates[templateIndex]
|
||||
analytics.captureEvent("Screen Created", {
|
||||
template: template.id || template.name,
|
||||
})
|
||||
}
|
||||
|
||||
finished()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,75 @@
|
|||
<script>
|
||||
import { DataList } from "@budibase/bbui"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { store } from "builderStore"
|
||||
import { store, backendUiStore } from "builderStore"
|
||||
import fetchBindableProperties from "builderStore/fetchBindableProperties"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
export let value = ""
|
||||
|
||||
$: urls = getUrls()
|
||||
|
||||
const handleBlur = () => dispatch("change", value)
|
||||
|
||||
// this will get urls of all screens, but only
|
||||
// choose detail screens that are usable in the current context
|
||||
// and substitute the :id param for the actual {{ ._id }} binding
|
||||
const getUrls = () => {
|
||||
const urls = [
|
||||
...$store.screens
|
||||
.filter(screen => !screen.props._component.endsWith("/rowdetail"))
|
||||
.map(screen => ({
|
||||
name: screen.props._instanceName,
|
||||
url: screen.route,
|
||||
sort: screen.props._component,
|
||||
})),
|
||||
]
|
||||
|
||||
const bindableProperties = fetchBindableProperties({
|
||||
componentInstanceId: $store.currentComponentInfo._id,
|
||||
components: $store.components,
|
||||
screen: $store.currentPreviewItem,
|
||||
models: $backendUiStore.models,
|
||||
})
|
||||
|
||||
const detailScreens = $store.screens.filter(screen =>
|
||||
screen.props._component.endsWith("/rowdetail")
|
||||
)
|
||||
|
||||
for (let detailScreen of detailScreens) {
|
||||
const idBinding = bindableProperties.find(p => {
|
||||
if (
|
||||
p.type === "context" &&
|
||||
p.runtimeBinding.endsWith("._id") &&
|
||||
p.model
|
||||
) {
|
||||
const modelId =
|
||||
typeof p.model === "string" ? p.model : p.model.modelId
|
||||
return modelId === detailScreen.props.model
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
if (idBinding) {
|
||||
urls.push({
|
||||
name: detailScreen.props._instanceName,
|
||||
url: detailScreen.route.replace(
|
||||
":id",
|
||||
`{{ ${idBinding.runtimeBinding} }}`
|
||||
),
|
||||
sort: detailScreen.props._component,
|
||||
})
|
||||
}
|
||||
|
||||
return urls
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<DataList editable secondary on:blur={handleBlur} on:change bind:value>
|
||||
<option value="" />
|
||||
{#each $store.allScreens as screen}
|
||||
<option value={screen.route}>{screen.props._instanceName}</option>
|
||||
{#each urls as url}
|
||||
<option value={url.url}>{url.name}</option>
|
||||
{/each}
|
||||
</DataList>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { isString, isUndefined } from "lodash/fp"
|
||||
import { isString, isUndefined, cloneDeep } from "lodash/fp"
|
||||
import { TYPE_MAP } from "./types"
|
||||
import { assign } from "lodash"
|
||||
import { uuid } from "builderStore/uuid"
|
||||
|
@ -83,13 +83,13 @@ const parsePropDef = propDef => {
|
|||
if (isString(propDef)) {
|
||||
if (!TYPE_MAP[propDef]) return error(`Type ${propDef} is not recognised.`)
|
||||
|
||||
return TYPE_MAP[propDef].default
|
||||
return cloneDeep(TYPE_MAP[propDef].default)
|
||||
}
|
||||
|
||||
const type = TYPE_MAP[propDef.type]
|
||||
if (!type) return error(`Type ${propDef.type} is not recognised.`)
|
||||
|
||||
return propDef.default
|
||||
return cloneDeep(propDef.default)
|
||||
}
|
||||
|
||||
export const arrayElementComponentName = (parentComponentName, arrayPropName) =>
|
||||
|
|
|
@ -10,7 +10,6 @@ export const TYPE_MAP = {
|
|||
},
|
||||
options: {
|
||||
default: [],
|
||||
options: [],
|
||||
},
|
||||
event: {
|
||||
default: [],
|
||||
|
|
|
@ -361,19 +361,18 @@ export const typography = [
|
|||
label: "Font",
|
||||
key: "font-family",
|
||||
control: OptionSelect,
|
||||
defaultValue: "initial",
|
||||
defaultValue: "Arial",
|
||||
options: [
|
||||
"initial",
|
||||
"Arial",
|
||||
"Arial Black",
|
||||
"Cursive",
|
||||
"Courier",
|
||||
"Comic Sans MS",
|
||||
"Helvetica",
|
||||
"Helvetica Neue",
|
||||
"Impact",
|
||||
"Inter",
|
||||
"Lucida Sans Unicode",
|
||||
"Open Sans",
|
||||
"Roboto",
|
||||
"Roboto Mono",
|
||||
"Times New Roman",
|
||||
|
@ -467,9 +466,9 @@ export const background = [
|
|||
label: "Gradient",
|
||||
key: "background-image",
|
||||
control: OptionSelect,
|
||||
defaultValue: "None",
|
||||
defaultValue: "",
|
||||
options: [
|
||||
{ label: "None", value: "None" },
|
||||
{ label: "Select option", value: "" },
|
||||
{
|
||||
label: "Warm Flame",
|
||||
value: "linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);",
|
||||
|
@ -518,9 +517,9 @@ export const background = [
|
|||
},
|
||||
{
|
||||
label: "Image",
|
||||
key: "background-image",
|
||||
key: "background",
|
||||
control: Input,
|
||||
placeholder: "Src",
|
||||
placeholder: "url",
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -665,7 +664,7 @@ export const transitions = [
|
|||
control: OptionSelect,
|
||||
textAlign: "center",
|
||||
placeholder: "sec",
|
||||
options: ["0.2ms", "0.4ms", "0.8ms", "1s", "2s", "4s"],
|
||||
options: ["0.4s", "0.6s", "0.8s", "1s", "2s", "4s"],
|
||||
},
|
||||
{
|
||||
label: "Ease",
|
||||
|
|
|
@ -386,7 +386,7 @@ export default {
|
|||
{
|
||||
label: "destinationUrl",
|
||||
key: "destinationUrl",
|
||||
control: Input,
|
||||
control: ScreenSelect,
|
||||
placeholder: "/table/_id",
|
||||
},
|
||||
],
|
||||
|
@ -435,7 +435,7 @@ export default {
|
|||
{
|
||||
label: "Link Url",
|
||||
key: "linkUrl",
|
||||
control: Input,
|
||||
control: ScreenSelect,
|
||||
placeholder: "Link URL",
|
||||
},
|
||||
{
|
||||
|
@ -510,7 +510,7 @@ export default {
|
|||
{
|
||||
label: "Link Url",
|
||||
key: "linkUrl",
|
||||
control: Input,
|
||||
control: ScreenSelect,
|
||||
placeholder: "Link URL",
|
||||
},
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ export const FIELDS = {
|
|||
type: "options",
|
||||
constraints: {
|
||||
type: "string",
|
||||
presence: { allowEmpty: true },
|
||||
presence: false,
|
||||
inclusion: [],
|
||||
},
|
||||
},
|
||||
|
@ -67,7 +67,7 @@ export const FIELDS = {
|
|||
type: "link",
|
||||
constraints: {
|
||||
type: "array",
|
||||
presence: { allowEmpty: true },
|
||||
presence: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ exports.save = async function(ctx) {
|
|||
views: {},
|
||||
...rest,
|
||||
}
|
||||
let renameDocs = []
|
||||
|
||||
// if the model obj had an _id then it will have been retrieved
|
||||
const oldModel = ctx.preExisting
|
||||
|
@ -49,14 +50,11 @@ exports.save = async function(ctx) {
|
|||
include_docs: true,
|
||||
})
|
||||
)
|
||||
|
||||
const docs = records.rows.map(({ doc }) => {
|
||||
renameDocs = records.rows.map(({ doc }) => {
|
||||
doc[_rename.updated] = doc[_rename.old]
|
||||
delete doc[_rename.old]
|
||||
return doc
|
||||
})
|
||||
|
||||
await db.bulkDocs(docs)
|
||||
delete modelToSave._rename
|
||||
}
|
||||
|
||||
|
@ -69,9 +67,6 @@ exports.save = async function(ctx) {
|
|||
modelView.schema = modelToSave.schema
|
||||
}
|
||||
|
||||
const result = await db.post(modelToSave)
|
||||
modelToSave._rev = result.rev
|
||||
|
||||
// update linked records
|
||||
await linkRecords.updateLinks({
|
||||
instanceId,
|
||||
|
@ -82,6 +77,14 @@ exports.save = async function(ctx) {
|
|||
oldModel: oldModel,
|
||||
})
|
||||
|
||||
// don't perform any updates until relationships have been
|
||||
// checked by the updateLinks function
|
||||
if (renameDocs.length !== 0) {
|
||||
await db.bulkDocs(renameDocs)
|
||||
}
|
||||
const result = await db.post(modelToSave)
|
||||
modelToSave._rev = result.rev
|
||||
|
||||
ctx.eventEmitter &&
|
||||
ctx.eventEmitter.emitModel(`model:save`, instanceId, modelToSave)
|
||||
|
||||
|
@ -105,11 +108,8 @@ exports.save = async function(ctx) {
|
|||
exports.destroy = async function(ctx) {
|
||||
const instanceId = ctx.user.instanceId
|
||||
const db = new CouchDB(instanceId)
|
||||
|
||||
const modelToDelete = await db.get(ctx.params.modelId)
|
||||
|
||||
await db.remove(modelToDelete)
|
||||
|
||||
// Delete all records for that model
|
||||
const records = await db.allDocs(
|
||||
getRecordParams(ctx.params.modelId, null, {
|
||||
|
@ -117,7 +117,7 @@ exports.destroy = async function(ctx) {
|
|||
})
|
||||
)
|
||||
await db.bulkDocs(
|
||||
records.rows.map(record => ({ _id: record.id, _deleted: true }))
|
||||
records.rows.map(record => ({ ...record.doc, _deleted: true }))
|
||||
)
|
||||
|
||||
// update linked records
|
||||
|
@ -127,6 +127,9 @@ exports.destroy = async function(ctx) {
|
|||
model: modelToDelete,
|
||||
})
|
||||
|
||||
// don't remove the table itself until very end
|
||||
await db.remove(modelToDelete)
|
||||
|
||||
ctx.eventEmitter &&
|
||||
ctx.eventEmitter.emitModel(`model:delete`, instanceId, modelToDelete)
|
||||
ctx.status = 200
|
||||
|
|
|
@ -136,7 +136,7 @@ exports.performLocalFileProcessing = async function(ctx) {
|
|||
}
|
||||
|
||||
exports.serveApp = async function(ctx) {
|
||||
const mainOrAuth = ctx.isAuthenticated ? "main" : "unauthenticated"
|
||||
const mainOrAuth = ctx.auth.authenticated ? "main" : "unauthenticated"
|
||||
|
||||
// default to homedir
|
||||
const appPath = resolve(
|
||||
|
@ -154,7 +154,7 @@ exports.serveApp = async function(ctx) {
|
|||
// only set the appId cookie for /appId .. we COULD check for valid appIds
|
||||
// but would like to avoid that DB hit
|
||||
const looksLikeAppId = /^(app_)?[0-9a-f]{32}$/.test(appId)
|
||||
if (looksLikeAppId && !ctx.isAuthenticated) {
|
||||
if (looksLikeAppId && !ctx.auth.authenticated) {
|
||||
const anonUser = {
|
||||
userId: "ANON",
|
||||
accessLevelId: ANON_LEVEL_ID,
|
||||
|
@ -200,7 +200,7 @@ exports.serveAttachment = async function(ctx) {
|
|||
|
||||
exports.serveAppAsset = async function(ctx) {
|
||||
// default to homedir
|
||||
const mainOrAuth = ctx.isAuthenticated ? "main" : "unauthenticated"
|
||||
const mainOrAuth = ctx.auth.authenticated ? "main" : "unauthenticated"
|
||||
|
||||
const appPath = resolve(
|
||||
budibaseAppsDir(),
|
||||
|
|
|
@ -24,6 +24,7 @@ app.use(
|
|||
)
|
||||
|
||||
app.context.eventEmitter = eventEmitter
|
||||
app.context.auth = {}
|
||||
|
||||
// api routes
|
||||
app.use(api.routes())
|
||||
|
|
|
@ -161,7 +161,7 @@ class LinkController {
|
|||
})
|
||||
// now add the docs to be deleted to the bulk operation
|
||||
operations.push(...toDeleteDocs)
|
||||
// replace this field with a simple entry to denote there are links
|
||||
// remove the field from this row, link doc will be added to record on way out
|
||||
delete record[fieldName]
|
||||
}
|
||||
}
|
||||
|
@ -234,8 +234,16 @@ class LinkController {
|
|||
for (let fieldName of Object.keys(schema)) {
|
||||
const field = schema[fieldName]
|
||||
if (field.type === "link") {
|
||||
// handle this in a separate try catch, want
|
||||
// the put to bubble up as an error, if can't update
|
||||
// table for some reason
|
||||
let linkedModel
|
||||
try {
|
||||
linkedModel = await this._db.get(field.modelId)
|
||||
} catch (err) {
|
||||
continue
|
||||
}
|
||||
// create the link field in the other model
|
||||
const linkedModel = await this._db.get(field.modelId)
|
||||
linkedModel.schema[field.fieldName] = {
|
||||
name: field.fieldName,
|
||||
type: "link",
|
||||
|
|
|
@ -42,6 +42,7 @@ exports.updateLinks = async function({
|
|||
model,
|
||||
oldModel,
|
||||
}) {
|
||||
const baseReturnObj = record == null ? model : record
|
||||
if (instanceId == null) {
|
||||
throw "Cannot operate without an instance ID."
|
||||
}
|
||||
|
@ -50,12 +51,16 @@ exports.updateLinks = async function({
|
|||
arguments[0].modelId = model._id
|
||||
}
|
||||
let linkController = new LinkController(arguments[0])
|
||||
if (
|
||||
!(await linkController.doesModelHaveLinkedFields()) &&
|
||||
(oldModel == null ||
|
||||
!(await linkController.doesModelHaveLinkedFields(oldModel)))
|
||||
) {
|
||||
return record
|
||||
try {
|
||||
if (
|
||||
!(await linkController.doesModelHaveLinkedFields()) &&
|
||||
(oldModel == null ||
|
||||
!(await linkController.doesModelHaveLinkedFields(oldModel)))
|
||||
) {
|
||||
return baseReturnObj
|
||||
}
|
||||
} catch (err) {
|
||||
return baseReturnObj
|
||||
}
|
||||
switch (eventType) {
|
||||
case EventType.RECORD_SAVE:
|
||||
|
|
|
@ -57,21 +57,26 @@ exports.generateModelID = () => {
|
|||
|
||||
/**
|
||||
* Gets the DB allDocs/query params for retrieving a record.
|
||||
* @param {string} modelId The model in which the records have been stored.
|
||||
* @param {string|null} modelId The model in which the records have been stored.
|
||||
* @param {string|null} recordId The ID of the record which is being specifically queried for. This can be
|
||||
* left null to get all the records in the model.
|
||||
* @param {object} otherProps Any other properties to add to the request.
|
||||
* @returns {object} Parameters which can then be used with an allDocs request.
|
||||
*/
|
||||
exports.getRecordParams = (modelId, recordId = null, otherProps = {}) => {
|
||||
exports.getRecordParams = (
|
||||
modelId = null,
|
||||
recordId = null,
|
||||
otherProps = {}
|
||||
) => {
|
||||
if (modelId == null) {
|
||||
throw "Cannot build params for records without a model ID"
|
||||
return getDocParams(DocumentTypes.RECORD, null, otherProps)
|
||||
} else {
|
||||
const endOfKey =
|
||||
recordId == null
|
||||
? `${modelId}${SEPARATOR}`
|
||||
: `${modelId}${SEPARATOR}${recordId}`
|
||||
return getDocParams(DocumentTypes.RECORD, endOfKey, otherProps)
|
||||
}
|
||||
const endOfKey =
|
||||
recordId == null
|
||||
? `${modelId}${SEPARATOR}`
|
||||
: `${modelId}${SEPARATOR}${recordId}`
|
||||
return getDocParams(DocumentTypes.RECORD, endOfKey, otherProps)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,7 +129,14 @@ exports.generateAutomationID = () => {
|
|||
* @returns {string} The new link doc ID which the automation doc can be stored under.
|
||||
*/
|
||||
exports.generateLinkID = (modelId1, modelId2, recordId1, recordId2) => {
|
||||
return `${DocumentTypes.AUTOMATION}${SEPARATOR}${modelId1}${SEPARATOR}${modelId2}${SEPARATOR}${recordId1}${SEPARATOR}${recordId2}`
|
||||
return `${DocumentTypes.LINK}${SEPARATOR}${modelId1}${SEPARATOR}${modelId2}${SEPARATOR}${recordId1}${SEPARATOR}${recordId2}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets parameters for retrieving link docs, this is a utility function for the getDocParams function.
|
||||
*/
|
||||
exports.getLinkParams = (otherProps = {}) => {
|
||||
return getDocParams(DocumentTypes.LINK, null, otherProps)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,8 +20,10 @@ module.exports = async (ctx, next) => {
|
|||
if (builderToken) {
|
||||
try {
|
||||
const jwtPayload = jwt.verify(builderToken, ctx.config.jwtSecret)
|
||||
ctx.apiKey = jwtPayload.apiKey
|
||||
ctx.isAuthenticated = jwtPayload.accessLevelId === BUILDER_LEVEL_ID
|
||||
ctx.auth = {
|
||||
apiKey: jwtPayload.apiKey,
|
||||
authenticated: jwtPayload.accessLevelId === BUILDER_LEVEL_ID,
|
||||
}
|
||||
ctx.user = {
|
||||
...jwtPayload,
|
||||
accessLevel: await getAccessLevel(
|
||||
|
@ -38,14 +40,13 @@ module.exports = async (ctx, next) => {
|
|||
}
|
||||
|
||||
if (!appToken) {
|
||||
ctx.isAuthenticated = false
|
||||
ctx.auth.authenticated = false
|
||||
await next()
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const jwtPayload = jwt.verify(appToken, ctx.config.jwtSecret)
|
||||
ctx.apiKey = jwtPayload.apiKey
|
||||
ctx.user = {
|
||||
...jwtPayload,
|
||||
accessLevel: await getAccessLevel(
|
||||
|
@ -53,7 +54,10 @@ module.exports = async (ctx, next) => {
|
|||
jwtPayload.accessLevelId
|
||||
),
|
||||
}
|
||||
ctx.isAuthenticated = ctx.user.accessLevelId !== ANON_LEVEL_ID
|
||||
ctx.auth = {
|
||||
authenticated: ctx.user.accessLevelId !== ANON_LEVEL_ID,
|
||||
apiKey: jwtPayload.apiKey,
|
||||
}
|
||||
} catch (err) {
|
||||
ctx.throw(err.status || STATUS_CODES.FORBIDDEN, err.text)
|
||||
}
|
||||
|
|
|
@ -5,9 +5,36 @@ const {
|
|||
BUILDER_LEVEL_ID,
|
||||
BUILDER,
|
||||
} = require("../utilities/accessLevels")
|
||||
const environment = require("../environment")
|
||||
const { apiKeyTable } = require("../db/dynamoClient")
|
||||
|
||||
module.exports = (permName, getItemId) => async (ctx, next) => {
|
||||
if (!ctx.isAuthenticated) {
|
||||
if (
|
||||
environment.CLOUD &&
|
||||
ctx.headers["x-api-key"] &&
|
||||
ctx.headers["x-instanceid"]
|
||||
) {
|
||||
// api key header passed by external webhook
|
||||
const apiKeyInfo = await apiKeyTable.get({
|
||||
primary: ctx.headers["x-api-key"],
|
||||
})
|
||||
|
||||
if (apiKeyInfo) {
|
||||
ctx.auth = {
|
||||
authenticated: true,
|
||||
external: true,
|
||||
apiKey: ctx.headers["x-api-key"],
|
||||
}
|
||||
ctx.user = {
|
||||
instanceId: ctx.headers["x-instanceid"],
|
||||
}
|
||||
return next()
|
||||
}
|
||||
|
||||
ctx.throw(403, "API key invalid")
|
||||
}
|
||||
|
||||
if (!ctx.auth.authenticated) {
|
||||
ctx.throw(403, "Session not authenticated")
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ module.exports = async (ctx, next) => {
|
|||
return next()
|
||||
}
|
||||
try {
|
||||
await usageQuota.update(ctx.apiKey, property, usage)
|
||||
await usageQuota.update(ctx.auth.apiKey, property, usage)
|
||||
return next()
|
||||
} catch (err) {
|
||||
ctx.throw(403, err)
|
||||
|
|
Loading…
Reference in New Issue