mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Added new member limit & removed old
refs: https://github.com/TryGhost/Team/issues/510 - The current member limit was implemented as a member-specific concept - The new limit service is much more generic, here we are swapping old for new - The updated concept here is blocking all publishing, not just email sending, when a site is over its member limit - To determine that we are publishing a post, we must be in the model layer. The code has been moved to the permissible function which makes sense as this is a permissions error that we are throwing - I've left the extra check for email retries in, in case there is some loophole here (but we may wish to change it)
This commit is contained in:
parent
e30b9735fa
commit
d51fcd072e
6 changed files with 13 additions and 45 deletions
|
@ -3,7 +3,6 @@ const {i18n} = require('../../lib/common');
|
|||
const errors = require('@tryghost/errors');
|
||||
const urlUtils = require('../../../shared/url-utils');
|
||||
const {mega} = require('../../services/mega');
|
||||
const membersService = require('../../services/members');
|
||||
const allowedIncludes = ['tags', 'authors', 'authors.roles', 'email'];
|
||||
const unsafeAttrs = ['status', 'authors', 'visibility'];
|
||||
|
||||
|
@ -154,11 +153,6 @@ module.exports = {
|
|||
unsafeAttrs: unsafeAttrs
|
||||
},
|
||||
async query(frame) {
|
||||
/**Check host limits for members when send email is true**/
|
||||
if ((frame.options.email_recipient_filter && frame.options.email_recipient_filter !== 'none') || frame.options.send_email_when_published) {
|
||||
await membersService.checkHostLimit();
|
||||
}
|
||||
|
||||
let model;
|
||||
if (!frame.options.email_recipient_filter && frame.options.send_email_when_published) {
|
||||
await models.Base.transaction(async (transacting) => {
|
||||
|
|
|
@ -3,7 +3,6 @@ const {i18n} = require('../../lib/common');
|
|||
const errors = require('@tryghost/errors');
|
||||
const urlUtils = require('../../../shared/url-utils');
|
||||
const {mega} = require('../../services/mega');
|
||||
const membersService = require('../../services/members');
|
||||
const allowedIncludes = ['tags', 'authors', 'authors.roles', 'email'];
|
||||
const unsafeAttrs = ['status', 'authors', 'visibility'];
|
||||
|
||||
|
@ -154,11 +153,6 @@ module.exports = {
|
|||
unsafeAttrs: unsafeAttrs
|
||||
},
|
||||
async query(frame) {
|
||||
/**Check host limits for members when send email is true**/
|
||||
if ((frame.options.email_recipient_filter && frame.options.email_recipient_filter !== 'none') || frame.options.send_email_when_published) {
|
||||
await membersService.checkHostLimit();
|
||||
}
|
||||
|
||||
let model;
|
||||
if (!frame.options.email_recipient_filter && frame.options.send_email_when_published) {
|
||||
await models.Base.transaction(async (transacting) => {
|
||||
|
|
|
@ -10,6 +10,7 @@ const htmlToPlaintext = require('../../shared/html-to-plaintext');
|
|||
const ghostBookshelf = require('./base');
|
||||
const config = require('../../shared/config');
|
||||
const settingsCache = require('../services/settings/cache');
|
||||
const limitService = require('../services/limits');
|
||||
const mobiledocLib = require('../lib/mobiledoc');
|
||||
const relations = require('./relations');
|
||||
const urlUtils = require('../../shared/url-utils');
|
||||
|
@ -1016,7 +1017,7 @@ Post = ghostBookshelf.Model.extend({
|
|||
},
|
||||
|
||||
// NOTE: the `authors` extension is the parent of the post model. It also has a permissible function.
|
||||
permissible: function permissible(postModel, action, context, unsafeAttrs, loadedPermissions, hasUserPermission, hasApiKeyPermission) {
|
||||
permissible: async function permissible(postModel, action, context, unsafeAttrs, loadedPermissions, hasUserPermission, hasApiKeyPermission) {
|
||||
let isContributor;
|
||||
let isOwner;
|
||||
let isAdmin;
|
||||
|
@ -1048,6 +1049,13 @@ Post = ghostBookshelf.Model.extend({
|
|||
isAdd = (action === 'add');
|
||||
isDestroy = (action === 'destroy');
|
||||
|
||||
if (limitService.isLimited('members')) {
|
||||
// You can't publish a post if you're over your member limit
|
||||
if ((isEdit && isChanging('status') && isDraft()) || (isAdd && isPublished())) {
|
||||
await limitService.errorIfIsOverLimit('members');
|
||||
}
|
||||
}
|
||||
|
||||
if (isContributor && isEdit) {
|
||||
// Only allow contributor edit if status is changing, and the post is a draft post
|
||||
hasUserPermission = !isChanging('status') && isDraft();
|
||||
|
|
|
@ -9,6 +9,7 @@ const {events, i18n} = require('../../lib/common');
|
|||
const logging = require('../../../shared/logging');
|
||||
const settingsCache = require('../settings/cache');
|
||||
const membersService = require('../members');
|
||||
const limitService = require('../limits');
|
||||
const bulkEmailService = require('../bulk-email');
|
||||
const jobsService = require('../jobs');
|
||||
const db = require('../../data/db');
|
||||
|
@ -253,7 +254,9 @@ async function sendEmailJob({emailModel, options}) {
|
|||
try {
|
||||
// Check host limit for allowed member count and throw error if over limit
|
||||
// - do this even if it's a retry so that there's no way around the limit
|
||||
await membersService.checkHostLimit();
|
||||
if (limitService.isLimited('members')) {
|
||||
await limitService.errorIfIsOverLimit('members');
|
||||
}
|
||||
|
||||
// Create email batch and recipient rows unless this is a retry and they already exist
|
||||
const existingBatchCount = await emailModel.related('emailBatches').count('id');
|
||||
|
|
|
@ -62,8 +62,6 @@ events.on('settings.edited', function updateSettingFromModel(settingModel) {
|
|||
const membersService = {
|
||||
contentGating: require('./content-gating'),
|
||||
|
||||
checkHostLimit: require('./limit'),
|
||||
|
||||
config: membersConfig,
|
||||
|
||||
get api() {
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
const config = require('../../../shared/config');
|
||||
const models = require('../../models');
|
||||
const errors = require('@tryghost/errors');
|
||||
|
||||
// Get total members direct from DB
|
||||
async function getTotalMembers() {
|
||||
return models.Member.count('id');
|
||||
}
|
||||
|
||||
module.exports = async () => {
|
||||
const membersHostLimit = config.get('hostSettings:limits:members');
|
||||
if (membersHostLimit) {
|
||||
const allowedMembersLimit = membersHostLimit.max;
|
||||
const hostUpgradeLink = config.get('hostSettings:limits').upgrade_url;
|
||||
|
||||
const totalMembers = await getTotalMembers();
|
||||
|
||||
if (totalMembers > allowedMembersLimit) {
|
||||
throw new errors.HostLimitError({
|
||||
message: `Your current plan allows you to have up to ${allowedMembersLimit} members, but you currently have ${totalMembers} members`,
|
||||
help: hostUpgradeLink,
|
||||
errorDetails: {
|
||||
limit: allowedMembersLimit,
|
||||
total: totalMembers
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
Loading…
Add table
Reference in a new issue