mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-17 23:44:39 -05:00
Added allowlist limit (#144)
issue https://github.com/TryGhost/Team/issues/510
This commit is contained in:
parent
8c6ec8b214
commit
8381346dce
3 changed files with 88 additions and 10 deletions
|
@ -1,4 +1,4 @@
|
||||||
const {MaxLimit, FlagLimit} = require('./limit');
|
const {MaxLimit, FlagLimit, AllowlistLimit} = require('./limit');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
@ -30,7 +30,9 @@ class LimitService {
|
||||||
/** @type LimitConfig */
|
/** @type LimitConfig */
|
||||||
let limitConfig = Object.assign({}, config[name], limits[name]);
|
let limitConfig = Object.assign({}, config[name], limits[name]);
|
||||||
|
|
||||||
if (_.has(limitConfig, 'max')) {
|
if (_.has(limitConfig, 'allowlist')) {
|
||||||
|
this.limits[name] = new AllowlistLimit({name, config: limitConfig, helpLink, errors});
|
||||||
|
} else if (_.has(limitConfig, 'max')) {
|
||||||
this.limits[name] = new MaxLimit({name: name, config: limitConfig, helpLink, db, errors});
|
this.limits[name] = new MaxLimit({name: name, config: limitConfig, helpLink, db, errors});
|
||||||
} else {
|
} else {
|
||||||
this.limits[name] = new FlagLimit({name: name, config: limitConfig, helpLink, errors});
|
this.limits[name] = new FlagLimit({name: name, config: limitConfig, helpLink, errors});
|
||||||
|
@ -58,13 +60,13 @@ class LimitService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkWouldGoOverLimit(limitName) {
|
async checkWouldGoOverLimit(limitName, metadata = {}) {
|
||||||
if (!this.isLimited(limitName)) {
|
if (!this.isLimited(limitName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.limits[limitName].errorIfWouldGoOverLimit();
|
await this.limits[limitName].errorIfWouldGoOverLimit(metadata);
|
||||||
return false;
|
return false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof this.errors.HostLimitError) {
|
if (error instanceof this.errors.HostLimitError) {
|
||||||
|
@ -73,20 +75,20 @@ class LimitService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async errorIfIsOverLimit(limitName) {
|
async errorIfIsOverLimit(limitName, metadata = {}) {
|
||||||
if (!this.isLimited(limitName)) {
|
if (!this.isLimited(limitName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.limits[limitName].errorIfIsOverLimit();
|
await this.limits[limitName].errorIfIsOverLimit(metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
async errorIfWouldGoOverLimit(limitName) {
|
async errorIfWouldGoOverLimit(limitName, metadata = {}) {
|
||||||
if (!this.isLimited(limitName)) {
|
if (!this.isLimited(limitName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.limits[limitName].errorIfWouldGoOverLimit();
|
await this.limits[limitName].errorIfWouldGoOverLimit(metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,51 @@ class FlagLimit extends Limit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AllowlistLimit extends Limit {
|
||||||
|
constructor({name, config, helpLink, errors}) {
|
||||||
|
super({name, error: config.error || '', helpLink, errors});
|
||||||
|
|
||||||
|
if (!config.allowlist || !config.allowlist.length) {
|
||||||
|
throw new this.errors.IncorrectUsageError('Attempted to setup an allowlist limit without an allowlist');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.allowlist = config.allowlist;
|
||||||
|
this.fallbackMessage = `This action would exceed the ${_.lowerCase(this.name)} limit on your current plan.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
generateError() {
|
||||||
|
let errorObj = super.generateError();
|
||||||
|
|
||||||
|
if (this.error) {
|
||||||
|
errorObj.message = this.error;
|
||||||
|
} else {
|
||||||
|
errorObj.message = this.fallbackMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new this.errors.HostLimitError(errorObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
async errorIfWouldGoOverLimit(metadata) {
|
||||||
|
if (!metadata.value) {
|
||||||
|
throw new this.errors.IncorrectUsageError('Attempted to check an allowlist limit without a value');
|
||||||
|
}
|
||||||
|
if (!this.allowlist.includes(metadata.value)) {
|
||||||
|
throw this.generateError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async errorIfIsOverLimit(metadata) {
|
||||||
|
if (!metadata.value) {
|
||||||
|
throw new this.errors.IncorrectUsageError('Attempted to check an allowlist limit without a value');
|
||||||
|
}
|
||||||
|
if (!this.allowlist.includes(metadata.value)) {
|
||||||
|
throw this.generateError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
MaxLimit,
|
MaxLimit,
|
||||||
FlagLimit
|
FlagLimit,
|
||||||
|
AllowlistLimit
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
require('./utils');
|
require('./utils');
|
||||||
|
|
||||||
const errors = require('./fixtures/errors');
|
const errors = require('./fixtures/errors');
|
||||||
const {MaxLimit} = require('../lib/limit');
|
const {MaxLimit, AllowlistLimit} = require('../lib/limit');
|
||||||
|
|
||||||
describe('Limit Service', function () {
|
describe('Limit Service', function () {
|
||||||
describe('Max Limit', function () {
|
describe('Max Limit', function () {
|
||||||
|
@ -167,4 +167,36 @@ describe('Limit Service', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Allowlist limit', function () {
|
||||||
|
it('rejects when the allowlist config isn\'t specified', async function () {
|
||||||
|
try {
|
||||||
|
new AllowlistLimit({name: 'test', config: {}, errors});
|
||||||
|
throw new Error('Should have failed earlier...');
|
||||||
|
} catch (error) {
|
||||||
|
error.errorType.should.equal('IncorrectUsageError');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accept correct values', async function () {
|
||||||
|
const limit = new AllowlistLimit({name: 'test', config: {
|
||||||
|
allowlist: ['test', 'ok']
|
||||||
|
}, errors});
|
||||||
|
|
||||||
|
await limit.errorIfIsOverLimit({value: 'test'});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects unkown values', async function () {
|
||||||
|
const limit = new AllowlistLimit({name: 'test', config: {
|
||||||
|
allowlist: ['test', 'ok']
|
||||||
|
}, errors});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await limit.errorIfIsOverLimit({value: 'unkown value'});
|
||||||
|
throw new Error('Should have failed earlier...');
|
||||||
|
} catch (error) {
|
||||||
|
error.errorType.should.equal('HostLimitError');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue