Better error handling around license errors

This commit is contained in:
Rory Powell 2022-03-16 17:29:47 +00:00
parent 953a5f881c
commit e695a57853
6 changed files with 56 additions and 26 deletions

View File

@ -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,
} }

View File

@ -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,
} }

View File

@ -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.")
} }
} }
} }

View File

@ -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)

View File

@ -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,

View File

@ -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,