Billing - Schema validation on update billing setting
ADD
src/assets/server/rest/v1/schemas/billing/billing-setting-update.json
+{
+ "title": "Update Billing Settings",
+ "type": "object",
+ "properties": {
+ "id": {
+ "$ref": "common.json#/definitions/id"
+ },
+ "identifier": {
+ "type": "string",
+ "sanitize": "mongo"
+ },
+ "type": {
+ "type": "string",
+ "sanitize": "mongo"
+ },
+ "billing": {
+ "type": "object",
+ "properties": {
+ "isTransactionBillingActivated": {
+ "type": "boolean",
+ "sanitize": "mongo"
+ },
+ "immediateBillingAllowed": {
+ "type": "boolean",
+ "sanitize": "mongo"
+ },
+ "periodicBillingAllowed": {
+ "type": "boolean",
+ "sanitize": "mongo"
+ },
+ "taxID": {
+ "type": "string",
+ "sanitize": "mongo"
+ }
+ },
+ "required": [
+ "isTransactionBillingActivated",
+ "immediateBillingAllowed",
+ "periodicBillingAllowed",
+ "taxID"
+ ]
+ },
+ "stripe": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string",
+ "sanitize": "mongo"
+ },
+ "publicKey": {
+ "type": "string",
+ "sanitize": "mongo"
+ },
+ "secretKey": {
+ "type": "string",
+ "sanitize": "mongo"
+ }
+ },
+ "required": [
+ "url",
+ "publicKey",
+ "secretKey"
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "identifier",
+ "type",
+ "billing"
+ ]
+}

MODIFY
src/server/rest/v1/service/BillingService.ts
src/server/rest/v1/service/BillingService.ts
@@ -11,6 +11,7 @@ import BillingFactory from '../../../../integration/billing/BillingFactory';
import BillingSecurity from './security/BillingSecurity';
import { BillingSettings } from '../../../../types/Setting';
import BillingStorage from '../../../../storage/mongodb/BillingStorage';
+import BillingValidator from '../validator/BillingValidator';
import Constants from '../../../../utils/Constants';
import Cypher from '../../../../utils/Cypher';
import { DataResult } from '../../../../types/DataResult';
@@ -33,6 +34,9 @@ const MODULE_NAME = 'BillingService';
export default class BillingService {
public static async handleCheckBillingConnection(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
+ // Check if component is active
+ UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING,
+ Action.CHECK_CONNECTION, Entity.BILLING, MODULE_NAME, 'handleCheckBillingConnection');
if (!await Authorizations.canCheckBillingConnection(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.FORBIDDEN,
@@ -41,9 +45,6 @@ export default class BillingService {
module: MODULE_NAME, method: 'handleCheckBillingConnection',
});
}
- // Check if component is active
- UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING,
- Action.CHECK_CONNECTION, Entity.BILLING, MODULE_NAME, 'handleCheckBillingConnection');
const billingImpl = await BillingFactory.getBillingImpl(req.user.tenantID);
if (!billingImpl) {
throw new AppError({
@@ -776,10 +777,8 @@ export default class BillingService {
// Check if component is active
UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING,
Action.UPDATE, Entity.SETTING, MODULE_NAME, 'handleUpdateBillingSetting');
- // Filter
- // TODO - sanitize it
- const newBillingProperties = req.body as Partial<BillingSettings>;
- UtilsService.assertIdIsProvided(action, newBillingProperties.id, MODULE_NAME, 'handleUpdateBillingSetting', req.user);
+ // Check
+ const newBillingProperties = BillingValidator.getInstance().validateUpdateBillingSetting({ ...req.params, ...req.body });
// Check auth
if (!await Authorizations.canUpdateBillingSetting(req.user)) {
throw new AppAuthError({

ADD
src/server/rest/v1/validator/BillingValidator.ts
+import AppError from '../../../../exception/AppError';
+import { BillingSettings } from '../../../../types/Setting';
+import Constants from '../../../../utils/Constants';
+import Schema from '../../../../types/validator/Schema';
+import SchemaValidator from './SchemaValidator';
+import fs from 'fs';
+import global from '../../../../types/GlobalType';
+
+export default class BillingValidator extends SchemaValidator {
+ private static instance: BillingValidator|null = null;
+ private updateBillingSetting: Schema;
+
+ private constructor() {
+ super('BillingValidator');
+ this.updateBillingSetting = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/billing/billing-setting-update.json`, 'utf8'));
+ }
+
+ public static getInstance(): BillingValidator {
+ if (!BillingValidator.instance) {
+ BillingValidator.instance = new BillingValidator();
+ }
+ return BillingValidator.instance;
+ }
+
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+ public validateUpdateBillingSetting(data: any): BillingSettings {
+ // Validate schema
+ this.validate(this.updateBillingSetting, data);
+ // Validate deps between components
+ // this.validateComponentDependencies(tenant);
+ return data;
+ }
+
+ // private validateComponentDependencies(tenant: Tenant): void {
+ // if (tenant.components) {
+ // if (!tenant.components.pricing?.active) {
+ // throw new AppError({
+ // source: Constants.CENTRAL_SERVER,
+ // errorCode: HTTPError.GENERAL_ERROR,
+ // message: 'Pricing component must be active to use the Billing module',
+ // module: this.moduleName, method: 'validateComponentDependencies'
+ // });
+ // }
+ // }
+ // }
+}

Billing - Schema validation on update billing setting