Better error handling around license errors
This commit is contained in:
parent
953a5f881c
commit
e695a57853
|
@ -8,8 +8,34 @@ const types = {
|
||||||
...licensing.types,
|
...licensing.types,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
...licensing.context,
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPublicError = err => {
|
||||||
|
let error
|
||||||
|
if (err.code || err.type) {
|
||||||
|
// add generic error information
|
||||||
|
error = {
|
||||||
|
code: err.code,
|
||||||
|
type: err.type,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err.code) {
|
||||||
|
error = {
|
||||||
|
...error,
|
||||||
|
// get any additional context from this error
|
||||||
|
...context[err.code](err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
codes,
|
codes,
|
||||||
types,
|
types,
|
||||||
UsageLimitError: licensing.UsageLimitError,
|
UsageLimitError: licensing.UsageLimitError,
|
||||||
|
getPublicError,
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,25 @@ const codes = {
|
||||||
USAGE_LIMIT_EXCEEDED: "usage_limit_exceeded",
|
USAGE_LIMIT_EXCEEDED: "usage_limit_exceeded",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
[codes.USAGE_LIMIT_EXCEEDED]: err => {
|
||||||
|
return {
|
||||||
|
limitName: err.limitName,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
class UsageLimitError extends BudibaseError {
|
class UsageLimitError extends BudibaseError {
|
||||||
constructor(message, limitName) {
|
constructor(message, limitName) {
|
||||||
super(message, types.LICENSE_ERROR, codes.USAGE_LIMIT_EXCEEDED)
|
super(message, types.LICENSE_ERROR, codes.USAGE_LIMIT_EXCEEDED)
|
||||||
this.limitName = limitName
|
this.limitName = limitName
|
||||||
|
this.status = 400
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
types,
|
types,
|
||||||
codes,
|
codes,
|
||||||
|
context,
|
||||||
UsageLimitError,
|
UsageLimitError,
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ exports.ObjectStore = bucket => {
|
||||||
const config = {
|
const config = {
|
||||||
s3ForcePathStyle: true,
|
s3ForcePathStyle: true,
|
||||||
signatureVersion: "v4",
|
signatureVersion: "v4",
|
||||||
|
apiVersion: "2006-03-01",
|
||||||
params: {
|
params: {
|
||||||
Bucket: sanitizeBucket(bucket),
|
Bucket: sanitizeBucket(bucket),
|
||||||
},
|
},
|
||||||
|
@ -102,17 +103,21 @@ exports.makeSureBucketExists = async (client, bucketName) => {
|
||||||
.promise()
|
.promise()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const promises = STATE.bucketCreationPromises
|
const promises = STATE.bucketCreationPromises
|
||||||
|
const doesntExist = err.statusCode === 404,
|
||||||
|
noAccess = err.statusCode === 403
|
||||||
if (promises[bucketName]) {
|
if (promises[bucketName]) {
|
||||||
await promises[bucketName]
|
await promises[bucketName]
|
||||||
} else if (err.statusCode === 404) {
|
} else if (doesntExist || noAccess) {
|
||||||
// bucket doesn't exist create it
|
if (doesntExist) {
|
||||||
promises[bucketName] = client
|
// bucket doesn't exist create it
|
||||||
.createBucket({
|
promises[bucketName] = client
|
||||||
Bucket: bucketName,
|
.createBucket({
|
||||||
})
|
Bucket: bucketName,
|
||||||
.promise()
|
})
|
||||||
await promises[bucketName]
|
.promise()
|
||||||
delete promises[bucketName]
|
await promises[bucketName]
|
||||||
|
delete promises[bucketName]
|
||||||
|
}
|
||||||
// public buckets are quite hidden in the system, make sure
|
// public buckets are quite hidden in the system, make sure
|
||||||
// no bucket is set accidentally
|
// no bucket is set accidentally
|
||||||
if (PUBLIC_BUCKETS.includes(bucketName)) {
|
if (PUBLIC_BUCKETS.includes(bucketName)) {
|
||||||
|
@ -124,7 +129,7 @@ exports.makeSureBucketExists = async (client, bucketName) => {
|
||||||
.promise()
|
.promise()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw err
|
throw new Error("Unable to write to object store bucket.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ const {
|
||||||
buildTenancyMiddleware,
|
buildTenancyMiddleware,
|
||||||
buildAppTenancyMiddleware,
|
buildAppTenancyMiddleware,
|
||||||
} = require("@budibase/backend-core/auth")
|
} = require("@budibase/backend-core/auth")
|
||||||
|
const { errors } = require("@budibase/backend-core")
|
||||||
const currentApp = require("../middleware/currentapp")
|
const currentApp = require("../middleware/currentapp")
|
||||||
const compress = require("koa-compress")
|
const compress = require("koa-compress")
|
||||||
const zlib = require("zlib")
|
const zlib = require("zlib")
|
||||||
|
@ -64,10 +65,12 @@ router.use(async (ctx, next) => {
|
||||||
await next()
|
await next()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.status = err.status || err.statusCode || 500
|
ctx.status = err.status || err.statusCode || 500
|
||||||
|
const error = errors.getPublicError(err)
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
message: err.message,
|
message: err.message,
|
||||||
status: ctx.status,
|
status: ctx.status,
|
||||||
validationErrors: err.validation,
|
validationErrors: err.validation,
|
||||||
|
error,
|
||||||
}
|
}
|
||||||
if (env.NODE_ENV !== "jest") {
|
if (env.NODE_ENV !== "jest") {
|
||||||
ctx.log.error(err)
|
ctx.log.error(err)
|
||||||
|
|
|
@ -134,7 +134,7 @@ const appPreDelete = async (ctx: any, usageContext: any) => {
|
||||||
|
|
||||||
const appPostDelete = async (ctx: any, usageContext: any) => {
|
const appPostDelete = async (ctx: any, usageContext: any) => {
|
||||||
// delete the app rows from usage
|
// delete the app rows from usage
|
||||||
const rowCount = usageContext[Pro.StaticQuotaName.ROWS].rowCount
|
const rowCount = usageContext[Pro.StaticQuotaName.APPS].rowCount
|
||||||
if (rowCount) {
|
if (rowCount) {
|
||||||
await Pro.Licensing.Quotas.updateUsage(
|
await Pro.Licensing.Quotas.updateUsage(
|
||||||
-rowCount,
|
-rowCount,
|
||||||
|
|
|
@ -113,21 +113,7 @@ router.use(async (ctx, next) => {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.log.error(err)
|
ctx.log.error(err)
|
||||||
ctx.status = err.status || err.statusCode || 500
|
ctx.status = err.status || err.statusCode || 500
|
||||||
|
const error = errors.getPublicError(err)
|
||||||
let error
|
|
||||||
if (err.code || err.type) {
|
|
||||||
// add generic error information
|
|
||||||
error = {
|
|
||||||
code: err.code,
|
|
||||||
type: err.type,
|
|
||||||
}
|
|
||||||
|
|
||||||
// add specific error information
|
|
||||||
if (error.code === errors.codes.USAGE_LIMIT_EXCEEDED) {
|
|
||||||
error.limitName = err.limitName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
message: err.message,
|
message: err.message,
|
||||||
status: ctx.status,
|
status: ctx.status,
|
||||||
|
|
Loading…
Reference in New Issue