diff --git a/server/src/http/controllers/Authentication.ts b/server/src/http/controllers/Authentication.ts index 83f74d632..45fc69bd7 100644 --- a/server/src/http/controllers/Authentication.ts +++ b/server/src/http/controllers/Authentication.ts @@ -139,6 +139,7 @@ export default class AuthenticationController extends BaseController{ const registeredUser: ISystemUser = await this.authService.register(registerDTO); return res.status(200).send({ + type: 'success', code: 'REGISTER.SUCCESS', message: 'Register organization has been success.', }); @@ -153,7 +154,7 @@ export default class AuthenticationController extends BaseController{ errorReasons.push({ type: 'EMAIL.EXISTS', code: 200 }); } if (errorReasons.length > 0) { - return res.status(200).send({ errors: errorReasons }); + return res.boom.badRequest(null, { errors: errorReasons }); } } next(); diff --git a/server/src/http/controllers/Items.ts b/server/src/http/controllers/Items.ts index 583b1accd..7a9b5accf 100644 --- a/server/src/http/controllers/Items.ts +++ b/server/src/http/controllers/Items.ts @@ -173,7 +173,6 @@ export default class ItemsController { const foundItems: [] = await Item.query().onBuild((builder: any) => { builder.where('name', item.name); - if (itemId) { builder.whereNot('id', itemId); } diff --git a/server/src/http/index.js b/server/src/http/index.ts similarity index 91% rename from server/src/http/index.js rename to server/src/http/index.ts index 0209bb39a..d2c1702a2 100644 --- a/server/src/http/index.js +++ b/server/src/http/index.ts @@ -33,9 +33,8 @@ import Resources from './controllers/Resources'; import ExchangeRates from '@/http/controllers/ExchangeRates'; import Media from '@/http/controllers/Media'; import Ping from '@/http/controllers/Ping'; -import Agendash from '@/http/controllers/Agendash'; import Subscription from '@/http/controllers/Subscription'; -import LicensesController from '@/http/controllers/Subscription/Licenses'; +import Licenses from '@/http/controllers/Subscription/Licenses'; export default () => { const app = Router(); @@ -45,11 +44,11 @@ export default () => { app.use('/auth', Container.get(Authentication).router()); app.use('/invite', Container.get(InviteUsers).nonAuthRouter()); app.use('/organization', Container.get(Organization).router()); - app.use('/licenses', Container.get(LicensesController).router()); + app.use('/licenses', Container.get(Licenses).router()); app.use('/subscription', Container.get(Subscription).router()); app.use('/ping', Container.get(Ping).router()); - const dashboard = Router(); + const dashboard = Router(); dashboard.use(JWTAuth); dashboard.use(AttachCurrentTenantUser) @@ -77,9 +76,8 @@ export default () => { dashboard.use('/purchases', Purchases.router()); dashboard.use('/resources', Resources.router()); dashboard.use('/exchange_rates', ExchangeRates.router()); - dashboard.use('/media', Media.router()); + dashboard.use('/media', Media.router()) - app.use('/agendash', Agendash.router()); app.use('/', dashboard); return app; diff --git a/server/src/http/middleware/ConfiguredMiddleware.js b/server/src/http/middleware/ConfiguredMiddleware.ts similarity index 61% rename from server/src/http/middleware/ConfiguredMiddleware.js rename to server/src/http/middleware/ConfiguredMiddleware.ts index 899053d91..40064320b 100644 --- a/server/src/http/middleware/ConfiguredMiddleware.js +++ b/server/src/http/middleware/ConfiguredMiddleware.ts @@ -1,6 +1,7 @@ +import { Container } from 'typedi'; +import { Request, Response, NextFunction } from 'express'; -// eslint-disable-next-line consistent-return -export default async (req, res, next) => { +export default async (req: Request, res: Response, next: NextFunction) => { const { Option } = req.models; const option = await Option.query().where('key', 'app_configured'); diff --git a/server/src/http/middleware/SubscriptionFeatureMiddleware.js b/server/src/http/middleware/SubscriptionFeatureMiddleware.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/server/src/http/middleware/SubscriptionMiddleware.js b/server/src/http/middleware/SubscriptionMiddleware.js deleted file mode 100644 index 1f38bc83d..000000000 --- a/server/src/http/middleware/SubscriptionMiddleware.js +++ /dev/null @@ -1,26 +0,0 @@ - -export default (subscriptionSlug = 'main') => async (req, res, next) => { - const { tenant } = req; - - if (!tenant) { - throw new Error('Should load `TenancyMiddlware` before this middleware.'); - } - const subscription = await tenant - .$relatedQuery('subscriptions') - .modify('subscriptionBySlug', subscriptionSlug) - .first(); - - // Validate in case there is no any already subscription. - if (!subscription) { - return res.status(400).send({ - errors: [{ type: 'TENANT.HAS.NO.SUBSCRIPTION' }], - }); - } - // Validate in case the subscription is inactive. - else if (subscription.inactive()) { - return res.status(400).send({ - errors: [{ type: 'ORGANIZATION.SUBSCRIPTION.INACTIVE' }], - }); - } - next(); -}; \ No newline at end of file diff --git a/server/src/http/middleware/SubscriptionMiddleware.ts b/server/src/http/middleware/SubscriptionMiddleware.ts new file mode 100644 index 000000000..0abde5237 --- /dev/null +++ b/server/src/http/middleware/SubscriptionMiddleware.ts @@ -0,0 +1,33 @@ +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'); + + if (!tenant) { + throw new Error('Should load `TenancyMiddlware` before this middleware.'); + } + Logger.info('[subscription_middleware] trying get tenant main subscription.'); + const subscription = await tenant + .$relatedQuery('subscriptions') + .modify('subscriptionBySlug', subscriptionSlug) + .first(); + + // 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(); +}; \ No newline at end of file diff --git a/server/src/http/middleware/TenancyMiddleware.js b/server/src/http/middleware/TenancyMiddleware.ts similarity index 93% rename from server/src/http/middleware/TenancyMiddleware.js rename to server/src/http/middleware/TenancyMiddleware.ts index be358e7d5..7ecd651bc 100644 --- a/server/src/http/middleware/TenancyMiddleware.js +++ b/server/src/http/middleware/TenancyMiddleware.ts @@ -1,8 +1,9 @@ import { Container } from 'typedi'; +import { Request, Response, NextFunction } from 'express'; import TenantsManager from '@/system/TenantsManager'; import tenantModelsLoader from '@/loaders/tenantModels'; -export default async (req, res, next) => { +export default async (req: Request, res: Response, next: NextFunction) => { const Logger = Container.get('logger'); const organizationId = req.headers['organization-id'] || req.query.organization; diff --git a/server/src/http/middleware/asyncMiddleware.js b/server/src/http/middleware/asyncMiddleware.js deleted file mode 100644 index 713dc1b7f..000000000 --- a/server/src/http/middleware/asyncMiddleware.js +++ /dev/null @@ -1,9 +0,0 @@ -const asyncMiddleware = (fn) => (req, res, next) => { - Promise.resolve(fn(req, res, next)) - .catch((error) => { - console.log(error); - next(error); - }); -}; - -export default asyncMiddleware; diff --git a/server/src/http/middleware/asyncMiddleware.ts b/server/src/http/middleware/asyncMiddleware.ts new file mode 100644 index 000000000..a8c0f747b --- /dev/null +++ b/server/src/http/middleware/asyncMiddleware.ts @@ -0,0 +1,17 @@ +import logger from "src/loaders/logger"; + +import { Request, Response, NextFunction } from 'express'; +import { Container } from 'typedi'; + +export default ( + fn: (rq: Request, rs: Response, next?: NextFunction) => {}) => + (req: Request, res: Response, next: NextFunction) => { + const Logger = Container.get('logger'); + + Promise.resolve(fn(req, res, next)) + .catch((error) => { + console.log(error); + Logger.error('[async_middleware] error.', { error }); + next(error); + }); +}; \ No newline at end of file diff --git a/server/src/http/middleware/jwtAuth.js b/server/src/http/middleware/jwtAuth.ts similarity index 85% rename from server/src/http/middleware/jwtAuth.js rename to server/src/http/middleware/jwtAuth.ts index 23188e334..c77709c01 100644 --- a/server/src/http/middleware/jwtAuth.js +++ b/server/src/http/middleware/jwtAuth.ts @@ -1,8 +1,9 @@ +import { Request, Response, NextFunction } from 'express'; import { Container } from 'typedi'; import jwt from 'jsonwebtoken'; import config from '@/../config/config'; -const authMiddleware = (req, res, next) => { +const authMiddleware = (req: Request, res: Response, next: NextFunction) => { const Logger = Container.get('logger'); const token = req.headers['x-access-token'] || req.query.token; diff --git a/server/src/interfaces/Account.ts b/server/src/interfaces/Account.ts new file mode 100644 index 000000000..64bfb6749 --- /dev/null +++ b/server/src/interfaces/Account.ts @@ -0,0 +1,15 @@ + + +export interface IAccountDTO { + name: string, + code: string, + description: string, + accountTypeNumber: number, +}; + +export interface IAccount { + name: string, + code: string, + description: string, + accountTypeNumber: number, +}; \ No newline at end of file diff --git a/server/src/interfaces/index.ts b/server/src/interfaces/index.ts index c8d7a9446..7b0c3355f 100644 --- a/server/src/interfaces/index.ts +++ b/server/src/interfaces/index.ts @@ -46,8 +46,15 @@ import { IOptionDTO, IOptionsDTO, } from './Options'; +import { + IAccount, + IAccountDTO, +} from './Account'; export { + IAccount, + IAccountDTO, + IBillPaymentEntry, IBillPayment, IBillPaymentOTD, diff --git a/server/src/loaders/express.ts b/server/src/loaders/express.ts index 254ef6cd8..c7ee429db 100644 --- a/server/src/loaders/express.ts +++ b/server/src/loaders/express.ts @@ -1,4 +1,4 @@ -import express from 'express'; +import { json, Request, Response, NextFunction } from 'express'; import helmet from 'helmet'; import boom from 'express-boom'; import errorHandler from 'errorhandler'; @@ -6,6 +6,7 @@ import fileUpload from 'express-fileupload'; import i18n from 'i18n'; import routes from '@/http'; import LoggerMiddleware from '@/http/middleware/LoggerMiddleware'; +import AgendashController from '@/http/controllers/Agendash'; import config from '@/../config/config'; export default ({ app }) => { @@ -22,7 +23,7 @@ export default ({ app }) => { app.use(boom()); // Parses both json and urlencoded. - app.use(express.json()); + app.use(json()); // Handle multi-media requests. app.use(fileUpload({ @@ -38,8 +39,11 @@ export default ({ app }) => { // Prefix all application routes. app.use(config.api.prefix, routes()); + // Agendash application load. + app.use('/agendash', AgendashController.router()); + // catch 404 and forward to error handler - app.use((req, res, next) => { + app.use((req: Request, res: Response, next: NextFunction) => { return res.boom.notFound(); }) }; \ No newline at end of file diff --git a/server/src/services/Accounts/AccountsService.ts b/server/src/services/Accounts/AccountsService.ts index 47d9ef9be..2fbe7e341 100644 --- a/server/src/services/Accounts/AccountsService.ts +++ b/server/src/services/Accounts/AccountsService.ts @@ -3,7 +3,6 @@ import TenancyService from '@/services/Tenancy/TenancyService'; import { ServiceError } from '@/exceptions'; import { IAccountDTO, IAccount } from '@/interfaces'; import { difference } from 'lodash'; -import { tenant } from 'config/config'; @Service() export default class AccountsService { @@ -137,6 +136,7 @@ export default class AccountsService { public async newAccount(tenantId: number, accountDTO: IAccountDTO) { const { Account } = this.tenancy.models(tenantId); + // Validate the account code uniquiness. if (accountDTO.code) { await this.isAccountCodeUniqueOrThrowError(tenantId, accountDTO.code); } diff --git a/server/src/services/Authentication/index.ts b/server/src/services/Authentication/index.ts index 461aa46c5..ae94d3f11 100644 --- a/server/src/services/Authentication/index.ts +++ b/server/src/services/Authentication/index.ts @@ -126,7 +126,7 @@ export default class AuthenticationService { this.logger.info('[register] Someone trying to register.'); await this.validateEmailAndPhoneUniqiness(registerDTO); - this.logger.info('[register] Creating a new tenant org.') + this.logger.info('[register] Creating a new tenant organization.') const tenant = await this.newTenantOrganization(); this.logger.info('[register] Trying hashing the password.') diff --git a/server/src/services/Users/UsersService.ts b/server/src/services/Users/UsersService.ts index 88d694e7b..56a4541c5 100644 --- a/server/src/services/Users/UsersService.ts +++ b/server/src/services/Users/UsersService.ts @@ -3,7 +3,6 @@ import TenancyService from '@/services/Tenancy/TenancyService'; import { SystemUser } from "@/system/models"; import { ServiceError, ServiceErrors } from "@/exceptions"; import { ISystemUser, ISystemUserDTO } from "@/interfaces"; -import { ISystemUser } from "src/interfaces"; @Service() export default class UsersService { @@ -20,9 +19,9 @@ export default class UsersService { async editUser(tenantId: number, userId: number, userDTO: ISystemUserDTO): Promise { const foundUsers = await SystemUser.query() .whereNot('id', userId) - .andWhere((q) => { - q.where('email', userDTO.email); - q.orWhere('phone_number', userDTO.phoneNumber); + .andWhere((query) => { + query.where('email', userDTO.email); + query.orWhere('phone_number', userDTO.phoneNumber); }) .where('tenant_id', tenantId);