mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-22 10:21:36 +03:00
21427ad73f
* Simplified db controller permissions options The existing objects were confusing because they did the same thing as setting permissions to true, but gave the impressions that something special was happening/required. * Added DB Backup Integration Role This will allow us to assign certain api_keys this role, in order to automate db backups * Allowed admin api_keys to have configurable roles This will allow keys for the admin api to do customised things such as db export * Added ghost-backup integration to fixtures * Added migrations for DB Backup Integration and role
86 lines
2.2 KiB
JavaScript
86 lines
2.2 KiB
JavaScript
const omit = require('lodash/omit');
|
|
const crypto = require('crypto');
|
|
const ghostBookshelf = require('./base');
|
|
const {Role} = require('./role');
|
|
|
|
/*
|
|
* Uses birthday problem estimation to calculate chance of collision
|
|
* d = 16^26 // 26 char hex string
|
|
* n = 10,000,000 // 10 million
|
|
*
|
|
* (-n x (n-1)) / 2d
|
|
* 1 - e^
|
|
*
|
|
*
|
|
* 17
|
|
* ~= 4 x 10^
|
|
*
|
|
* ref: https://medium.freecodecamp.org/how-long-should-i-make-my-api-key-833ebf2dc26f
|
|
* ref: https://en.wikipedia.org/wiki/Birthday_problem#Approximations
|
|
*
|
|
* 26 char hex string = 13 bytes
|
|
* 64 char hex string JWT secret = 32 bytes
|
|
*/
|
|
const createSecret = (type) => {
|
|
const bytes = type === 'content' ? 13 : 32;
|
|
return crypto.randomBytes(bytes).toString('hex');
|
|
};
|
|
|
|
const ApiKey = ghostBookshelf.Model.extend({
|
|
tableName: 'api_keys',
|
|
|
|
defaults() {
|
|
const secret = createSecret(this.get('type'));
|
|
|
|
return {
|
|
secret
|
|
};
|
|
},
|
|
|
|
role() {
|
|
return this.belongsTo('Role');
|
|
},
|
|
|
|
integration() {
|
|
return this.belongsTo('Integration');
|
|
},
|
|
|
|
format(attrs) {
|
|
return omit(attrs, 'role');
|
|
},
|
|
|
|
onSaving(model, attrs, options) {
|
|
ghostBookshelf.Model.prototype.onSaving.apply(this, arguments);
|
|
|
|
// enforce roles which are currently hardcoded
|
|
// - admin key = Adminstrator role
|
|
// - content key = no role
|
|
if (this.hasChanged('type') || this.hasChanged('role_id')) {
|
|
if (this.get('type') === 'admin') {
|
|
return Role.findOne({name: attrs.role || 'Admin Integration'}, Object.assign({}, options, {columns: ['id']}))
|
|
.then((role) => {
|
|
this.set('role_id', role.get('id'));
|
|
});
|
|
}
|
|
|
|
if (this.get('type') === 'content') {
|
|
this.set('role_id', null);
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
refreshSecret(data, options) {
|
|
const secret = createSecret(data.type);
|
|
return this.edit(Object.assign({}, data, {secret}), options);
|
|
}
|
|
});
|
|
|
|
const ApiKeys = ghostBookshelf.Collection.extend({
|
|
model: ApiKey
|
|
});
|
|
|
|
module.exports = {
|
|
ApiKey: ghostBookshelf.model('ApiKey', ApiKey),
|
|
ApiKeys: ghostBookshelf.collection('ApiKeys', ApiKeys)
|
|
};
|