Ghost/ghost/admin/app/services/limit.js
Simon Backx 2d4bbad094 Implemented newsletter limits
refs https://github.com/TryGhost/Team/issues/1583

- When adding a newsletter, check the limits (both via button and route)
- When unarchiving a newsletter, check the limits
- Bumped `@tryghost/limit-service` package, required to make limit checking work for newsletter
- Added the `getNewslettersCount` query to the `limit` service
2022-05-11 12:10:26 +02:00

106 lines
3.1 KiB
JavaScript

import LimitService from '@tryghost/limit-service';
import RSVP from 'rsvp';
import Service, {inject as service} from '@ember/service';
import {bind} from '@ember/runloop';
class LimitError {
constructor({errorType, errorDetails, message}) {
this.errorType = errorType;
this.errorDetails = errorDetails;
this.message = message;
}
}
class IncorrectUsageError extends LimitError {
constructor(options) {
super(Object.assign({errorType: 'IncorrectUsageError'}, options));
}
}
class HostLimitError extends LimitError {
constructor(options) {
super(Object.assign({errorType: 'HostLimitError'}, options));
}
}
export default class LimitsService extends Service {
@service config;
@service store;
@service membersStats;
constructor() {
super(...arguments);
let limits = this.config.get('hostSettings.limits');
this.limiter = new LimitService();
if (!limits) {
return;
}
let helpLink;
if (this.config.get('hostSettings.billing.enabled')
&& this.config.get('hostSettings.billing.enabled') === true
&& this.config.get('hostSettings.billing.url')) {
helpLink = this.config.get('hostSettings.billing.url');
} else {
helpLink = 'https://ghost.org/help/';
}
return this.limiter.loadLimits({
limits: this.decorateWithCountQueries(limits),
helpLink,
errors: {
HostLimitError,
IncorrectUsageError
}
});
}
async checkWouldGoOverLimit(limitName, metadata = {}) {
return this.limiter.checkWouldGoOverLimit(limitName, metadata);
}
decorateWithCountQueries(limits) {
if (limits.staff) {
limits.staff.currentCountQuery = bind(this, this.getStaffUsersCount);
}
if (limits.members) {
limits.members.currentCountQuery = bind(this, this.getMembersCount);
}
if (limits.newsletters) {
limits.newsletters.currentCountQuery = bind(this, this.getNewslettersCount);
}
return limits;
}
async getStaffUsersCount() {
return RSVP.hash({
users: this.store.findAll('user', {reload: true}),
invites: this.store.findAll('invite', {reload: true}),
roles: this.store.findAll('role', {reload: true}) // NOTE: roles have to be fetched as they are not always loaded with invites
}).then((data) => {
const staffUsers = data.users.filter(u => u.get('status') !== 'inactive' && u.role.get('name') !== 'Contributor');
const staffInvites = data.invites.filter(i => i.role.get('name') !== 'Contributor');
return staffUsers.length + staffInvites.length;
});
}
async getMembersCount() {
const counts = await this.membersStats.fetchCounts();
return counts.total;
}
async getNewslettersCount() {
const activeNewsletters = await this.store.query('newsletter', {filter: 'status:active', limit: 'all'});
return activeNewsletters.length;
}
}