mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 22:00:31 +00:00
feat(server): deprecated the subscription module.
This commit is contained in:
@@ -6,7 +6,6 @@ import { check, ValidationChain } from 'express-validator';
|
|||||||
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
|
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
|
||||||
import JWTAuth from '@/api/middleware/jwtAuth';
|
import JWTAuth from '@/api/middleware/jwtAuth';
|
||||||
import TenancyMiddleware from '@/api/middleware/TenancyMiddleware';
|
import TenancyMiddleware from '@/api/middleware/TenancyMiddleware';
|
||||||
import SubscriptionMiddleware from '@/api/middleware/SubscriptionMiddleware';
|
|
||||||
import AttachCurrentTenantUser from '@/api/middleware/AttachCurrentTenantUser';
|
import AttachCurrentTenantUser from '@/api/middleware/AttachCurrentTenantUser';
|
||||||
import OrganizationService from '@/services/Organization/OrganizationService';
|
import OrganizationService from '@/services/Organization/OrganizationService';
|
||||||
import {
|
import {
|
||||||
@@ -24,7 +23,7 @@ const ACCEPTED_LOCATIONS = ['libya'];
|
|||||||
@Service()
|
@Service()
|
||||||
export default class OrganizationController extends BaseController {
|
export default class OrganizationController extends BaseController {
|
||||||
@Inject()
|
@Inject()
|
||||||
organizationService: OrganizationService;
|
private organizationService: OrganizationService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router constructor.
|
* Router constructor.
|
||||||
@@ -32,13 +31,10 @@ export default class OrganizationController extends BaseController {
|
|||||||
router() {
|
router() {
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
// Should before build tenant database the user be authorized and
|
|
||||||
// most important than that, should be subscribed to any plan.
|
|
||||||
router.use(JWTAuth);
|
router.use(JWTAuth);
|
||||||
router.use(AttachCurrentTenantUser);
|
router.use(AttachCurrentTenantUser);
|
||||||
router.use(TenancyMiddleware);
|
router.use(TenancyMiddleware);
|
||||||
|
|
||||||
router.use('/build', SubscriptionMiddleware('main'));
|
|
||||||
router.post(
|
router.post(
|
||||||
'/build',
|
'/build',
|
||||||
this.organizationValidationSchema,
|
this.organizationValidationSchema,
|
||||||
|
|||||||
@@ -1,250 +0,0 @@
|
|||||||
import { Service, Inject } from 'typedi';
|
|
||||||
import { Router, Request, Response, NextFunction } from 'express';
|
|
||||||
import { check, oneOf, ValidationChain } from 'express-validator';
|
|
||||||
import basicAuth from 'express-basic-auth';
|
|
||||||
import config from '@/config';
|
|
||||||
import { License } from '@/system/models';
|
|
||||||
import { ServiceError } from '@/exceptions';
|
|
||||||
import BaseController from '@/api/controllers/BaseController';
|
|
||||||
import LicenseService from '@/services/Payment/License';
|
|
||||||
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
|
|
||||||
import { ILicensesFilter, ISendLicenseDTO } from '@/interfaces';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export default class LicensesController extends BaseController {
|
|
||||||
@Inject()
|
|
||||||
licenseService: LicenseService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Router constructor.
|
|
||||||
*/
|
|
||||||
router() {
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
router.use(
|
|
||||||
basicAuth({
|
|
||||||
users: {
|
|
||||||
[config.licensesAuth.user]: config.licensesAuth.password,
|
|
||||||
},
|
|
||||||
challenge: true,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
router.post(
|
|
||||||
'/generate',
|
|
||||||
this.generateLicenseSchema,
|
|
||||||
this.validationResult,
|
|
||||||
asyncMiddleware(this.generateLicense.bind(this)),
|
|
||||||
this.catchServiceErrors,
|
|
||||||
);
|
|
||||||
router.post(
|
|
||||||
'/disable/:licenseId',
|
|
||||||
this.validationResult,
|
|
||||||
asyncMiddleware(this.disableLicense.bind(this)),
|
|
||||||
this.catchServiceErrors,
|
|
||||||
);
|
|
||||||
router.post(
|
|
||||||
'/send',
|
|
||||||
this.sendLicenseSchemaValidation,
|
|
||||||
this.validationResult,
|
|
||||||
asyncMiddleware(this.sendLicense.bind(this)),
|
|
||||||
this.catchServiceErrors,
|
|
||||||
);
|
|
||||||
router.delete(
|
|
||||||
'/:licenseId',
|
|
||||||
asyncMiddleware(this.deleteLicense.bind(this)),
|
|
||||||
this.catchServiceErrors,
|
|
||||||
);
|
|
||||||
router.get('/', asyncMiddleware(this.listLicenses.bind(this)));
|
|
||||||
return router;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate license validation schema.
|
|
||||||
*/
|
|
||||||
get generateLicenseSchema(): ValidationChain[] {
|
|
||||||
return [
|
|
||||||
check('loop').exists().isNumeric().toInt(),
|
|
||||||
check('period').exists().isNumeric().toInt(),
|
|
||||||
check('period_interval')
|
|
||||||
.exists()
|
|
||||||
.isIn(['month', 'months', 'year', 'years', 'day', 'days']),
|
|
||||||
check('plan_slug').exists().trim().escape(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specific license validation schema.
|
|
||||||
*/
|
|
||||||
get specificLicenseSchema(): ValidationChain[] {
|
|
||||||
return [
|
|
||||||
oneOf(
|
|
||||||
[check('license_id').exists().isNumeric().toInt()],
|
|
||||||
[check('license_code').exists().isNumeric().toInt()]
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send license validation schema.
|
|
||||||
*/
|
|
||||||
get sendLicenseSchemaValidation(): ValidationChain[] {
|
|
||||||
return [
|
|
||||||
check('period').exists().isNumeric(),
|
|
||||||
check('period_interval').exists().trim().escape(),
|
|
||||||
check('plan_slug').exists().trim().escape(),
|
|
||||||
oneOf([
|
|
||||||
check('phone_number').exists().trim().escape(),
|
|
||||||
check('email').exists().trim().escape(),
|
|
||||||
]),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate licenses codes with given period in bulk.
|
|
||||||
* @param {Request} req
|
|
||||||
* @param {Response} res
|
|
||||||
* @return {Response}
|
|
||||||
*/
|
|
||||||
async generateLicense(req: Request, res: Response, next: Function) {
|
|
||||||
const { loop = 10, period, periodInterval, planSlug } = this.matchedBodyData(
|
|
||||||
req
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.licenseService.generateLicenses(
|
|
||||||
loop,
|
|
||||||
period,
|
|
||||||
periodInterval,
|
|
||||||
planSlug
|
|
||||||
);
|
|
||||||
return res.status(200).send({
|
|
||||||
code: 100,
|
|
||||||
type: 'LICENSEES.GENERATED.SUCCESSFULLY',
|
|
||||||
message: 'The licenses have been generated successfully.',
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable the given license on the storage.
|
|
||||||
* @param {Request} req
|
|
||||||
* @param {Response} res
|
|
||||||
* @return {Response}
|
|
||||||
*/
|
|
||||||
async disableLicense(req: Request, res: Response, next: Function) {
|
|
||||||
const { licenseId } = req.params;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.licenseService.disableLicense(licenseId);
|
|
||||||
|
|
||||||
return res.status(200).send({ license_id: licenseId });
|
|
||||||
} catch (error) {
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the given license code on the storage.
|
|
||||||
* @param {Request} req
|
|
||||||
* @param {Response} res
|
|
||||||
* @return {Response}
|
|
||||||
*/
|
|
||||||
async deleteLicense(req: Request, res: Response, next: Function) {
|
|
||||||
const { licenseId } = req.params;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.licenseService.deleteLicense(licenseId);
|
|
||||||
|
|
||||||
return res.status(200).send({ license_id: licenseId });
|
|
||||||
} catch (error) {
|
|
||||||
next(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send license code in the given period to the customer via email or phone number
|
|
||||||
* @param {Request} req
|
|
||||||
* @param {Response} res
|
|
||||||
* @return {Response}
|
|
||||||
*/
|
|
||||||
async sendLicense(req: Request, res: Response, next: Function) {
|
|
||||||
const sendLicenseDTO: ISendLicenseDTO = this.matchedBodyData(req);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.licenseService.sendLicenseToCustomer(sendLicenseDTO);
|
|
||||||
|
|
||||||
return res.status(200).send({
|
|
||||||
status: 100,
|
|
||||||
code: 'LICENSE.CODE.SENT',
|
|
||||||
message: 'The license has been sent to the given customer.',
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listing licenses.
|
|
||||||
* @param {Request} req
|
|
||||||
* @param {Response} res
|
|
||||||
*/
|
|
||||||
async listLicenses(req: Request, res: Response) {
|
|
||||||
const filter: ILicensesFilter = {
|
|
||||||
disabled: false,
|
|
||||||
used: false,
|
|
||||||
sent: false,
|
|
||||||
active: false,
|
|
||||||
...req.query,
|
|
||||||
};
|
|
||||||
const licenses = await License.query().onBuild((builder) => {
|
|
||||||
builder.modify('filter', filter);
|
|
||||||
builder.orderBy('createdAt', 'ASC');
|
|
||||||
});
|
|
||||||
return res.status(200).send({ licenses });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Catches all service errors.
|
|
||||||
*/
|
|
||||||
catchServiceErrors(error, req: Request, res: Response, next: NextFunction) {
|
|
||||||
if (error instanceof ServiceError) {
|
|
||||||
if (error.errorType === 'PLAN_NOT_FOUND') {
|
|
||||||
return res.status(400).send({
|
|
||||||
errors: [{
|
|
||||||
type: 'PLAN.NOT.FOUND',
|
|
||||||
code: 100,
|
|
||||||
message: 'The given plan not found.',
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (error.errorType === 'LICENSE_NOT_FOUND') {
|
|
||||||
return res.status(400).send({
|
|
||||||
errors: [{
|
|
||||||
type: 'LICENSE_NOT_FOUND',
|
|
||||||
code: 200,
|
|
||||||
message: 'The given license id not found.'
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (error.errorType === 'LICENSE_ALREADY_DISABLED') {
|
|
||||||
return res.status(400).send({
|
|
||||||
errors: [{
|
|
||||||
type: 'LICENSE.ALREADY.DISABLED',
|
|
||||||
code: 200,
|
|
||||||
message: 'License is already disabled.'
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (error.errorType === 'NO_AVALIABLE_LICENSE_CODE') {
|
|
||||||
return res.status(400).send({
|
|
||||||
status: 110,
|
|
||||||
message: 'There is no licenses availiable right now with the given period and plan.',
|
|
||||||
code: 'NO.AVALIABLE.LICENSE.CODE',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import { Inject } from 'typedi';
|
|
||||||
import { Request, Response } from 'express';
|
|
||||||
import { Plan } from '@/system/models';
|
|
||||||
import BaseController from '@/api/controllers/BaseController';
|
|
||||||
import SubscriptionService from '@/services/Subscription/SubscriptionService';
|
|
||||||
|
|
||||||
export default class PaymentMethodController extends BaseController {
|
|
||||||
@Inject()
|
|
||||||
subscriptionService: SubscriptionService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the given plan slug exists on the storage.
|
|
||||||
*
|
|
||||||
* @param {Request} req
|
|
||||||
* @param {Response} res
|
|
||||||
* @param {NextFunction} next
|
|
||||||
*
|
|
||||||
* @return {Response|void}
|
|
||||||
*/
|
|
||||||
async validatePlanSlugExistance(req: Request, res: Response, next: Function) {
|
|
||||||
const { planSlug } = this.matchedBodyData(req);
|
|
||||||
const foundPlan = await Plan.query().where('slug', planSlug).first();
|
|
||||||
|
|
||||||
if (!foundPlan) {
|
|
||||||
return res.status(400).send({
|
|
||||||
errors: [{ type: 'PLAN.SLUG.NOT.EXISTS', code: 110 }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import { NextFunction, Router, Request, Response } from 'express';
|
|
||||||
import { check } from 'express-validator';
|
|
||||||
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
|
|
||||||
import PaymentMethodController from '@/api/controllers/Subscription/PaymentMethod';
|
|
||||||
import {
|
|
||||||
NotAllowedChangeSubscriptionPlan,
|
|
||||||
NoPaymentModelWithPricedPlan,
|
|
||||||
PaymentAmountInvalidWithPlan,
|
|
||||||
PaymentInputInvalid,
|
|
||||||
VoucherCodeRequired,
|
|
||||||
} from '@/exceptions';
|
|
||||||
import { ILicensePaymentModel } from '@/interfaces';
|
|
||||||
import instance from 'tsyringe/dist/typings/dependency-container';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export default class PaymentViaLicenseController extends PaymentMethodController {
|
|
||||||
@Inject('logger')
|
|
||||||
logger: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Router constructor.
|
|
||||||
*/
|
|
||||||
router() {
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
'/payment',
|
|
||||||
this.paymentViaLicenseSchema,
|
|
||||||
this.validationResult,
|
|
||||||
asyncMiddleware(this.validatePlanSlugExistance.bind(this)),
|
|
||||||
asyncMiddleware(this.paymentViaLicense.bind(this)),
|
|
||||||
this.handleErrors,
|
|
||||||
);
|
|
||||||
return router;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Payment via license validation schema.
|
|
||||||
*/
|
|
||||||
get paymentViaLicenseSchema() {
|
|
||||||
return [
|
|
||||||
check('plan_slug').exists().trim().escape(),
|
|
||||||
check('license_code').exists().trim().escape(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the subscription payment via license code.
|
|
||||||
* @param {Request} req
|
|
||||||
* @param {Response} res
|
|
||||||
* @return {Response}
|
|
||||||
*/
|
|
||||||
async paymentViaLicense(req: Request, res: Response, next: Function) {
|
|
||||||
const { planSlug, licenseCode } = this.matchedBodyData(req);
|
|
||||||
const { tenant } = req;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const licenseModel: ILicensePaymentModel = { licenseCode };
|
|
||||||
|
|
||||||
await this.subscriptionService.subscriptionViaLicense(
|
|
||||||
tenant.id,
|
|
||||||
planSlug,
|
|
||||||
licenseModel
|
|
||||||
);
|
|
||||||
|
|
||||||
return res.status(200).send({
|
|
||||||
type: 'success',
|
|
||||||
code: 'PAYMENT.SUCCESSFULLY.MADE',
|
|
||||||
message: 'Payment via license has been made successfully.',
|
|
||||||
});
|
|
||||||
} catch (exception) {
|
|
||||||
next(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle service errors.
|
|
||||||
* @param {Error} error
|
|
||||||
* @param {Request} req
|
|
||||||
* @param {Response} res
|
|
||||||
* @param {NextFunction} next
|
|
||||||
*/
|
|
||||||
private handleErrors(
|
|
||||||
exception: Error,
|
|
||||||
req: Request,
|
|
||||||
res: Response,
|
|
||||||
next: NextFunction
|
|
||||||
) {
|
|
||||||
const errorReasons = [];
|
|
||||||
|
|
||||||
if (exception instanceof VoucherCodeRequired) {
|
|
||||||
errorReasons.push({
|
|
||||||
type: 'VOUCHER_CODE_REQUIRED',
|
|
||||||
code: 100,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (exception instanceof NoPaymentModelWithPricedPlan) {
|
|
||||||
errorReasons.push({
|
|
||||||
type: 'NO_PAYMENT_WITH_PRICED_PLAN',
|
|
||||||
code: 140,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (exception instanceof NotAllowedChangeSubscriptionPlan) {
|
|
||||||
errorReasons.push({
|
|
||||||
type: 'NOT.ALLOWED.RENEW.SUBSCRIPTION.WHILE.ACTIVE',
|
|
||||||
code: 120,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (errorReasons.length > 0) {
|
|
||||||
return res.status(400).send({ errors: errorReasons });
|
|
||||||
}
|
|
||||||
if (exception instanceof PaymentInputInvalid) {
|
|
||||||
return res.status(400).send({
|
|
||||||
errors: [{ type: 'LICENSE.CODE.IS.INVALID', code: 120 }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (exception instanceof PaymentAmountInvalidWithPlan) {
|
|
||||||
return res.status(400).send({
|
|
||||||
errors: [{ type: 'LICENSE.NOT.FOR.GIVEN.PLAN' }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
next(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import { Router, Request, Response, NextFunction } from 'express';
|
|
||||||
import { Container, Service, Inject } from 'typedi';
|
|
||||||
import JWTAuth from '@/api/middleware/jwtAuth';
|
|
||||||
import TenancyMiddleware from '@/api/middleware/TenancyMiddleware';
|
|
||||||
import AttachCurrentTenantUser from '@/api/middleware/AttachCurrentTenantUser';
|
|
||||||
import PaymentViaLicenseController from '@/api/controllers/Subscription/PaymentViaLicense';
|
|
||||||
import SubscriptionService from '@/services/Subscription/SubscriptionService';
|
|
||||||
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export default class SubscriptionController {
|
|
||||||
@Inject()
|
|
||||||
subscriptionService: SubscriptionService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Router constructor.
|
|
||||||
*/
|
|
||||||
router() {
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
router.use(JWTAuth);
|
|
||||||
router.use(AttachCurrentTenantUser);
|
|
||||||
router.use(TenancyMiddleware);
|
|
||||||
|
|
||||||
router.use('/license', Container.get(PaymentViaLicenseController).router());
|
|
||||||
router.get('/', asyncMiddleware(this.getSubscriptions.bind(this)));
|
|
||||||
|
|
||||||
return router;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve all subscriptions of the authenticated user's tenant.
|
|
||||||
* @param {Request} req
|
|
||||||
* @param {Response} res
|
|
||||||
* @param {NextFunction} next
|
|
||||||
*/
|
|
||||||
async getSubscriptions(req: Request, res: Response, next: NextFunction) {
|
|
||||||
const { tenantId } = req;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const subscriptions = await this.subscriptionService.getSubscriptions(
|
|
||||||
tenantId
|
|
||||||
);
|
|
||||||
return res.status(200).send({ subscriptions });
|
|
||||||
} catch (error) {
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,6 @@ import { Container } from 'typedi';
|
|||||||
// Middlewares
|
// Middlewares
|
||||||
import JWTAuth from '@/api/middleware/jwtAuth';
|
import JWTAuth from '@/api/middleware/jwtAuth';
|
||||||
import AttachCurrentTenantUser from '@/api/middleware/AttachCurrentTenantUser';
|
import AttachCurrentTenantUser from '@/api/middleware/AttachCurrentTenantUser';
|
||||||
import SubscriptionMiddleware from '@/api/middleware/SubscriptionMiddleware';
|
|
||||||
import TenancyMiddleware from '@/api/middleware/TenancyMiddleware';
|
import TenancyMiddleware from '@/api/middleware/TenancyMiddleware';
|
||||||
import EnsureTenantIsInitialized from '@/api/middleware/EnsureTenantIsInitialized';
|
import EnsureTenantIsInitialized from '@/api/middleware/EnsureTenantIsInitialized';
|
||||||
import SettingsMiddleware from '@/api/middleware/SettingsMiddleware';
|
import SettingsMiddleware from '@/api/middleware/SettingsMiddleware';
|
||||||
@@ -37,8 +36,6 @@ import Resources from './controllers/Resources';
|
|||||||
import ExchangeRates from '@/api/controllers/ExchangeRates';
|
import ExchangeRates from '@/api/controllers/ExchangeRates';
|
||||||
import Media from '@/api/controllers/Media';
|
import Media from '@/api/controllers/Media';
|
||||||
import Ping from '@/api/controllers/Ping';
|
import Ping from '@/api/controllers/Ping';
|
||||||
import Subscription from '@/api/controllers/Subscription';
|
|
||||||
import Licenses from '@/api/controllers/Subscription/Licenses';
|
|
||||||
import InventoryAdjustments from '@/api/controllers/Inventory/InventoryAdjustments';
|
import InventoryAdjustments from '@/api/controllers/Inventory/InventoryAdjustments';
|
||||||
import asyncRenderMiddleware from './middleware/AsyncRenderMiddleware';
|
import asyncRenderMiddleware from './middleware/AsyncRenderMiddleware';
|
||||||
import Jobs from './controllers/Jobs';
|
import Jobs from './controllers/Jobs';
|
||||||
@@ -69,8 +66,6 @@ export default () => {
|
|||||||
|
|
||||||
app.use('/auth', Container.get(Authentication).router());
|
app.use('/auth', Container.get(Authentication).router());
|
||||||
app.use('/invite', Container.get(InviteUsers).nonAuthRouter());
|
app.use('/invite', Container.get(InviteUsers).nonAuthRouter());
|
||||||
app.use('/licenses', Container.get(Licenses).router());
|
|
||||||
app.use('/subscription', Container.get(Subscription).router());
|
|
||||||
app.use('/organization', Container.get(Organization).router());
|
app.use('/organization', Container.get(Organization).router());
|
||||||
app.use('/ping', Container.get(Ping).router());
|
app.use('/ping', Container.get(Ping).router());
|
||||||
app.use('/jobs', Container.get(Jobs).router());
|
app.use('/jobs', Container.get(Jobs).router());
|
||||||
@@ -83,7 +78,6 @@ export default () => {
|
|||||||
dashboard.use(JWTAuth);
|
dashboard.use(JWTAuth);
|
||||||
dashboard.use(AttachCurrentTenantUser);
|
dashboard.use(AttachCurrentTenantUser);
|
||||||
dashboard.use(TenancyMiddleware);
|
dashboard.use(TenancyMiddleware);
|
||||||
dashboard.use(SubscriptionMiddleware('main'));
|
|
||||||
dashboard.use(EnsureTenantIsInitialized);
|
dashboard.use(EnsureTenantIsInitialized);
|
||||||
dashboard.use(SettingsMiddleware);
|
dashboard.use(SettingsMiddleware);
|
||||||
dashboard.use(I18nAuthenticatedMiddlware);
|
dashboard.use(I18nAuthenticatedMiddlware);
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
import { Request, Response, NextFunction } from 'express';
|
|
||||||
import { Container } from 'typedi';
|
|
||||||
|
|
||||||
export default (subscriptionSlug = 'main') => async (
|
|
||||||
req: Request,
|
|
||||||
res: Response,
|
|
||||||
next: NextFunction
|
|
||||||
) => {
|
|
||||||
const { tenant, tenantId } = req;
|
|
||||||
const Logger = Container.get('logger');
|
|
||||||
const { subscriptionRepository } = Container.get('repositories');
|
|
||||||
|
|
||||||
if (!tenant) {
|
|
||||||
throw new Error('Should load `TenancyMiddlware` before this middleware.');
|
|
||||||
}
|
|
||||||
Logger.info('[subscription_middleware] trying get tenant main subscription.');
|
|
||||||
const subscription = await subscriptionRepository.getBySlugInTenant(
|
|
||||||
subscriptionSlug,
|
|
||||||
tenantId
|
|
||||||
);
|
|
||||||
// Validate in case there is no any already subscription.
|
|
||||||
if (!subscription) {
|
|
||||||
Logger.info('[subscription_middleware] tenant has no subscription.', {
|
|
||||||
tenantId,
|
|
||||||
});
|
|
||||||
return res.boom.badRequest('Tenant has no subscription.', {
|
|
||||||
errors: [{ type: 'TENANT.HAS.NO.SUBSCRIPTION' }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Validate in case the subscription is inactive.
|
|
||||||
else if (subscription.inactive()) {
|
|
||||||
Logger.info(
|
|
||||||
'[subscription_middleware] tenant main subscription is expired.',
|
|
||||||
{ tenantId }
|
|
||||||
);
|
|
||||||
return res.boom.badRequest(null, {
|
|
||||||
errors: [{ type: 'ORGANIZATION.SUBSCRIPTION.INACTIVE' }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
};
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
exports.up = function(knex) {
|
|
||||||
return knex.schema.createTable('subscriptions_plans', table => {
|
|
||||||
table.increments();
|
|
||||||
|
|
||||||
table.string('name');
|
|
||||||
table.string('description');
|
|
||||||
table.decimal('price');
|
|
||||||
table.string('currency', 3);
|
|
||||||
|
|
||||||
table.integer('trial_period');
|
|
||||||
table.string('trial_interval');
|
|
||||||
|
|
||||||
table.integer('invoice_period');
|
|
||||||
table.string('invoice_interval');
|
|
||||||
table.timestamps();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = function(knex) {
|
|
||||||
return knex.schema.dropTableIfExists('subscriptions_plans')
|
|
||||||
};
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
|
|
||||||
exports.up = function(knex) {
|
|
||||||
return knex.schema.createTable('subscription_plans', table => {
|
|
||||||
table.increments();
|
|
||||||
table.string('slug');
|
|
||||||
table.string('name');
|
|
||||||
table.string('desc');
|
|
||||||
table.boolean('active');
|
|
||||||
|
|
||||||
table.decimal('price').unsigned();
|
|
||||||
table.string('currency', 3);
|
|
||||||
|
|
||||||
table.decimal('trial_period').nullable();
|
|
||||||
table.string('trial_interval').nullable();
|
|
||||||
|
|
||||||
table.decimal('invoice_period').nullable();
|
|
||||||
table.string('invoice_interval').nullable();
|
|
||||||
|
|
||||||
table.integer('index').unsigned();
|
|
||||||
table.timestamps();
|
|
||||||
}).then(() => {
|
|
||||||
return knex.seed.run({
|
|
||||||
specific: 'seed_subscriptions_plans.js',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = function(knex) {
|
|
||||||
return knex.schema.dropTableIfExists('subscription_plans')
|
|
||||||
};
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
|
|
||||||
exports.up = function(knex) {
|
|
||||||
return knex.schema.createTable('subscription_plan_features', table => {
|
|
||||||
table.increments();
|
|
||||||
table.integer('plan_id').unsigned().index().references('id').inTable('subscription_plans');
|
|
||||||
table.string('slug');
|
|
||||||
table.string('name');
|
|
||||||
table.string('description');
|
|
||||||
table.timestamps();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = function(knex) {
|
|
||||||
return knex.schema.dropTableIfExists('subscription_plan_features');
|
|
||||||
};
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
exports.up = function(knex) {
|
|
||||||
return knex.schema.createTable('subscription_plan_subscriptions', table => {
|
|
||||||
table.increments('id');
|
|
||||||
table.string('slug');
|
|
||||||
|
|
||||||
table.integer('plan_id').unsigned().index().references('id').inTable('subscription_plans');
|
|
||||||
table.bigInteger('tenant_id').unsigned().index().references('id').inTable('tenants');
|
|
||||||
|
|
||||||
table.dateTime('starts_at').nullable();
|
|
||||||
table.dateTime('ends_at').nullable();
|
|
||||||
|
|
||||||
table.dateTime('cancels_at').nullable();
|
|
||||||
table.dateTime('canceled_at').nullable();
|
|
||||||
|
|
||||||
table.timestamps();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = function(knex) {
|
|
||||||
return knex.schema.dropTableIfExists('subscription_plan_subscriptions');
|
|
||||||
};
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
exports.up = function(knex) {
|
|
||||||
return knex.schema.createTable('subscription_licenses', (table) => {
|
|
||||||
table.increments();
|
|
||||||
|
|
||||||
table.string('license_code').unique().index();
|
|
||||||
table.integer('plan_id').unsigned().index().references('id').inTable('subscription_plans');
|
|
||||||
|
|
||||||
table.integer('license_period').unsigned();
|
|
||||||
table.string('period_interval');
|
|
||||||
|
|
||||||
table.dateTime('sent_at').index();
|
|
||||||
table.dateTime('disabled_at').index();
|
|
||||||
table.dateTime('used_at').index();
|
|
||||||
|
|
||||||
table.timestamps();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = function(knex) {
|
|
||||||
return knex.schema.dropTableIfExists('subscription_licenses');
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user