Commit 3124c058 authored by Anh Nga's avatar Anh Nga

no message

parents
Pipeline #3372 passed with stages
in 9 minutes and 21 seconds
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 4
# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[Makefile]
indent_style = tab
[*.md]
trim_trailing_whitespace = false
# Created by https://www.gitignore.io/api/node
### Node ###
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
local
.idea
build
src/**/*.yaml
!src/configs/template.yaml
# Firebase
*firebase*.json
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.DS_Store
# Required
image: docker:17.03.0-ce
services:
- docker:17.03.0-ce-dind
# --------
stages:
- build
- release
- deploy
.build: &build_template
stage: build
image: vothanhkiet/alpine-node-builder:latest
script:
- npm install --quiet
- gulp build:staging
cache:
untracked: true
key: "$CI_JOB_STAGE/$CI_COMMIT_REF_NAME"
paths:
- node_modules/
artifacts:
name: archive
expire_in: 1 week
paths:
- release/
.release: &release_template
stage: release
before_script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.ventuso.net
script:
- cd release
- docker build -t $CI_REGISTRY_IMAGE:$CI_BUILD_REF_NAME --rm=true .
- docker push $CI_REGISTRY_IMAGE:$CI_BUILD_REF_NAME
.deploy: &deploy_template
stage: deploy
image: vothanhkiet/alpine-node:7.2.1
before_script:
- eval $(ssh-agent -s)
- mkdir -p ~/.ssh
- echo "$SSH_ID_KEY" >> ~/.ssh/id_rsa
- chmod 400 ~/.ssh/id_rsa
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
script:
- echo "Deploy to staging server"
- ssh $USER@$HOST "mkdir -p $DEPLOY_FOLDER && cd $DEPLOY_FOLDER && curl $DEPLOY_PLAN > docker-compose.yaml && docker-compose pull && docker-compose down && docker-compose up -d"
build:
<<: *build_template
only:
- develop
- test
- staging
- master
- tags
release:
<<: *release_template
only:
- develop
- test
- staging
- master
- tags
deploy_dev:
<<: *deploy_template
variables:
DEPLOY_FOLDER: ~/projects/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME-$CI_COMMIT_REF_NAME
DEPLOY_PLAN: $DEV_DEPLOY_PLAN
USER: $VENTUSO_PC3_USER
HOST: $VENTUSO_PC3_IP
SSH_ID_KEY: $SSH_PRIVATE_KEY
only:
- develop
deploy_staging:
<<: *deploy_template
variables:
DEPLOY_FOLDER: ~/projects/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME-$CI_COMMIT_REF_NAME
DEPLOY_PLAN: $STAGING_DEPLOY_PLAN
USER: $VENTUSO_PC3_USER
HOST: $VENTUSO_PC3_IP
SSH_ID_KEY: $SSH_PRIVATE_KEY
only:
- staging
{
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules/",
"build/"
],
"extension": [
".ts"
],
"require": [
"ts-node/register --project ./"
],
"reporter": [
"text-summary",
"html"
],
"sourceMap": true,
"instrument": true
}
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"protocol": "inspector",
"name": "Debug server.ts",
"stopOnEntry": false,
"program": "${workspaceRoot}/src/server.ts",
"cwd": "${workspaceRoot}",
"sourceMaps": true,
"preLaunchTask": null,
"runtimeExecutable": null,
"runtimeArgs": [
"--nolazy"
],
"console": "integratedTerminal",
"outFiles": [
"${workspaceRoot}/build/**/*.js"
],
"env": {
"NODE_ENV": "development",
"TZ" : "UTC"
}
},
{
"type": "node",
"request": "launch",
"protocol": "inspector",
"name": "Profile server.ts",
"stopOnEntry": false,
"program": "${workspaceRoot}/src/server.ts",
"cwd": "${workspaceRoot}",
"sourceMaps": true,
"preLaunchTask": null,
"runtimeExecutable": null,
"runtimeArgs": [
"--nolazy",
"--prof"
],
"console": "integratedTerminal",
"outFiles": [
"${workspaceRoot}/build/**/*.js"
],
"env": {
"NODE_ENV": "development",
"TZ" : "UTC"
}
},
{
"type": "node",
"request": "launch",
"name": "Debug mocha",
"protocol": "auto",
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
"stopOnEntry": false,
"args": ["test/**/*.ts", "--no-timeouts"],
"cwd": "${workspaceRoot}",
"runtimeExecutable": null,
"env": {
"NODE_ENV": "test"
}
},
{
"type": "node",
"request": "attach",
"protocol": "auto",
"name": "Attach to Process",
"sourceMaps": true,
"port": 5858,
"outFiles": ["${workspaceRoot}/build/**/*.js"]
}
]
}
\ No newline at end of file
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "0.1.0",
"command": "gulp",
"isShellCommand": true,
"showOutput": "always",
"args": [
"--no-color"
],
"tasks": [
{
"taskName": "watch",
"args": [],
"isBuildCommand": true,
"isBackground": false,
"problemMatcher": [
"$lessCompile",
"$tsc",
"$jshint"
]
},
{
"taskName": "test",
"args": [],
"isTestCommand": true
}
]
}
\ No newline at end of file
#ignore specific files for tslint
!lines.js
!parse.js
!lintError.js
#ignore specific files for clean-css
!url-rewriter.js
!url-rebase.js
#ignore specific files for braintree
!credit_card_defaults.js
!credit_card_numbers.js
!merchant_account.js
!nonces.js
!transaction_amounts.js
!venmo_sdk.js
!test.js
# test directories
__tests__
test
tests
powered-test
# asset directories
docs
doc
website
images
assets
# examples
example
examples
# code coverage directories
coverage
.nyc_output
# build scripts
Makefile
Gulpfile.js
Gruntfile.js
# configs
.tern-project
.gitattributes
.editorconfig
.*ignore
.eslintrc
.jshintrc
.flowconfig
.documentup.json
.yarn-metadata.json
.*.yml
*.yml
# misc
*.gz
*.md
*.markdown
LICENSE
LICENSE.BSD
LICENSE.DOCS
AUTHORS
install:
npm install --silent -g npm
npm install --silent -g gulp-cli
npm install --silent -g tsc
npm install --silent
build: install
gulp clean
gulp build
release: install
gulp clean
gulp build:release
clean:
gulp clean
docker-up:
docker-compose up -d
docker-down:
docker-compose down
\ No newline at end of file
Ventuso's Visis Service
version: '2.1'
services:
postgres:
image: postgres:9.6.2-alpine
ports:
- 5432:5432
networks:
- internal
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=vivis
volumes:
- ${PWD}/local/postgres:/var/lib/postgresql/data
- ${PWD}/docker/development/postgres/initdb.d:/docker-entrypoint-initdb.d
redis:
image: redis:3.2.8-alpine
ports:
- 6379:6379
networks:
- internal
volumes:
- ${PWD}/local/redis:/data
redis-ui:
image: diyan/redis-commander
networks:
- internal
ports:
- 3010:8081
command: --redis-host redis
minio:
image: minio/minio:RELEASE.2017-09-29T19-16-56Z
networks:
- internal
ports:
- 9000:9000
environment:
- MINIO_ACCESS_KEY=access_key
- MINIO_SECRET_KEY=secret_key
command: server /export
volumes:
- $PWD/local/minio/export:/export
- $PWD/local/minio/config:/root/.minio
astray:
image: registry.ventuso.net/rd/astray:staging
networks:
- internal
ports:
- 3005:3000
environment:
- AWS_ACCESS_KEY_ID=access_key
- AWS_SECRET_ACCESS_KEY=secret_key
- S3_BUCKET=docker
- S3_ENDPOINT=http://minio:9000/
- DRIVERS=minio
create_bucket:
image: garland/aws-cli-docker
networks:
- internal
depends_on:
- minio
environment:
- AWS_ACCESS_KEY_ID=access_key
- AWS_SECRET_ACCESS_KEY=secret_key
- AWS_DEFAULT_REGION=us-east-1
command: >
/bin/sh -c "
while ! nc -vz minio 9000; do sleep 1; done;
echo Connected!;
date;
aws configure set default.s3.signature_version s3v4;
aws configure set default.region us-east-1;
aws s3api create-bucket \
--bucket docker \
--endpoint-url=http://minio:9000;"
# Note: https://docs.docker.com/docker-for-mac/networking/
# rabbitmq:
# image: rabbitmq:3.6.8-alpine
# container_name: rabbitmq
# ports:
# - 5672:5672
# networks:
# - internal
# volumes:
# - ${PWD}/local/rabbitmq:/var/lib/rabbitmq
# elastic:
# image: elasticsearch:5.1.1-alpine
# container_name: elastic
# ports:
# - 9200:9200
# networks:
# - internal
# kibana:
# image: kibana:5.1.1
# container_name: kibana
# ports:
# - 3003:5601
# networks:
# - internal
# environment:
# - ELASTICSEARCH_URL=http://elastic:9200
# depends_on:
# - elastic
# - logstash
# logstash:
# image: logstash:5.1.1
# container_name: logstash
# networks:
# - internal
# volumes:
# - ./build/logs:/home/logstash/logs
# - ./docker/development/logstash:/logstash
# command: logstash -f /logstash/log.conf
# depends_on:
# - elastic
networks:
internal:
input {
file {
path => "/home/logstash/logs/process.log"
type=> "process"
start_position => "beginning"
codec => "json"
}
}
filter {
date {
match => [ "timestamp", "yyyy-MM-dd'T'HH:mm:ss.SSSZ"]
}
}
output {
elasticsearch {
hosts => ["elastic:9200"]
}
}
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
FROM vothanhkiet/alpine-s6-node-native:8.7.0
WORKDIR /app
COPY ./app /app
ADD ./root /
RUN cd /app && \
npm install --quiet
RUN npm rebuild bcrypt --build-from-source
RUN npm rebuild grpc --build-from-source
RUN rm -rf /var/cache/apk/* /root/.npm /root/.node-gyp /tmp/* /var/tmp/*
EXPOSE 3000
#!/usr/bin/with-contenv sh
echo "Download setting from ${CONFIG_URL}"
curl ${CONFIG_URL} > /app/configs/configuration.yaml
if [ -n "$FIREBASE_URL" ]; then
curl ${FIREBASE_URL} > /app/configs/firebase.json
else
echo "Firebase key's URL was not found. Skip"
fi
cd /app && node server.js
/**
* Created by kiettv on 12/16/16.
*/
'use strict';
const argv = require('yargs').argv;
const path = require('path');
const gulp = require('gulp');
const file = require('gulp-file');
const ts = require('gulp-typescript');
const clean = require('gulp-clean');
const server = require('gulp-develop-server');
const sourcemaps = require('gulp-sourcemaps');
const uglify = require('gulp-uglify');
const tslint = require('gulp-tslint');
const plumber = require('gulp-plumber');
const zip = require('gulp-zip');
const jEditor = require('gulp-json-editor');
const runSequence = require('run-sequence');
const mocha = require('gulp-spawn-mocha');
const gUtil = require('gulp-util');
const istanbul = require('gulp-istanbul');
const merge = require('merge2');
const tsProject = ts.createProject('tsconfig.json');
const projects = {
bootstrap: 'server.js',
folders: {
src: 'src',
docker: 'docker',
build: 'build',
dist: 'release',
logs: 'logs',
coverage: 'coverage',
nyc: '.nyc_output',
migration: 'src/data/sql/migrations'
},
files: {
tsFiles: ['src/**/*.ts'],
nonTsFiles: ['src/**/*.*', 'src/**/*.**', '!src/**/*.ts'],
artifact: 'archive.zip',
configFiles: ['src/configs/*.yaml', '!src/configs/template.yaml']
}
};
const padDate = (segment) => {
segment = segment.toString();
return segment[1] ? segment : '0' + segment;
}
const yyyymmddhhmmss = () => {
var d = new Date();
return d.getFullYear().toString() + padDate(d.getMonth() + 1) + padDate(d.getDate()) + padDate(d.getHours()) + padDate(d.getMinutes()) + padDate(d.getSeconds());
}
gulp.task('clean', () => {
return gulp
.src([
projects.folders.build,
projects.folders.logs,
projects.folders.dist,
projects.folders.coverage,
projects.folders.nyc
], {
read: false
})
.pipe(clean());
});
gulp.task('files:copy', () => {
return gulp.src(projects.files.nonTsFiles)
.pipe(plumber())
.pipe(gulp.dest(projects.folders.build));
});
gulp.task('ts:lint', () =>
gulp.src(projects.files.tsFiles)
.pipe(tslint({
configuration: 'tslint.json'
}))
.pipe(tslint.report({
emitError: false
}))
);
gulp.task('ts:lint:release', () =>
gulp.src(projects.files.tsFiles)
.pipe(tslint({
configuration: 'tslint.json'
}))
.pipe(tslint.report({
emitError: true
}))
.on('error', (error) => {
process.exit(1);
})
);
gulp.task('ts:compile', () => {
let tsResult = gulp.src(projects.files.tsFiles, {
base: projects.folders.src
})
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(tsProject());
return merge([
tsResult.js.pipe(sourcemaps.write('.', {
includeContent: false,
sourceRoot: () => {
return path.join(__dirname, projects.folders.src);
}
}))
.pipe(gulp.dest(projects.folders.build))
]);
});
gulp.task('ts:compile:release', () => {
let tsResult = gulp.src(projects.files.tsFiles, {
base: projects.folders.src
})
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(tsProject());
// .on('error', function (error) {
// process.exit(1);
// });
return merge([
tsResult.js.pipe(sourcemaps.write('.', {
includeContent: false,
sourceRoot: () => {
return path.join(__dirname, projects.folders.src);
}
}))
.pipe(gulp.dest(projects.folders.build))
]);
});
gulp.task('files:copy:package.json', () => {
return gulp.src('package.json')
.pipe(jEditor(json => {
json.devDependencies = {};
return json;
}))
.pipe(gulp.dest(projects.folders.build));
});
gulp.task('zip', () => {
return gulp.src(projects.folders.build + '/**/*', {
dot: true
})
.pipe(zip(projects.files.artifact))
.pipe(gulp.dest(projects.folders.dist));
});
gulp.task('build', (cb) => {
runSequence('clean', 'ts:lint', 'files:copy', 'ts:compile', cb);
});
gulp.task('files:copy:docker', () => {
gulp.src(projects.folders.build + '/**')
.pipe(gulp.dest(projects.folders.dist + '/app'));
gulp.src(projects.folders.docker + '/production/**')
.pipe(gulp.dest(projects.folders.dist));
});
gulp.task('build:production', (cb) => {
runSequence('clean', 'ts:lint:release', 'files:copy', 'ts:compile:release', 'files:copy:package.json', 'files:copy:docker', cb)
});
gulp.task('build:staging', (cb) => {
runSequence('clean', 'ts:lint:release', 'files:copy', 'ts:compile:release', 'files:copy:package.json', 'files:copy:docker', cb)
});
gulp.task('build:release', (cb) => {
runSequence('clean', 'ts:lint:release', 'files:copy', 'ts:compile:release', 'files:copy:package.json', cb);
});
gulp.task('release', (cb) => {
runSequence('build:release', 'zip', cb);
});
gulp.task('test', () => {
return gulp.src(['test/*.ts'], {
read: false
})
.pipe(mocha({
reporter: 'spec',
compilers: 'ts:ts-node/register'
}))
.on('error', gUtil.log);
});
gulp.task('watch', ['build'], (cb) => {
gulp.watch(projects.files.tsFiles, ['ts:lint', 'ts:compile']);
gulp.watch(projects.files.nonTsFiles, ['files:copy']);
});
gulp.task('server:start', (cb) => {
runSequence('files:copy', 'ts:compile', cb);
server.listen({
path: `${projects.folders.build}/${projects.bootstrap}`
}, (error) => {
console.log(error);
});
});
gulp.task('server:restart', ['ts:compile'], () => {
server.restart();
});
gulp.task('default', ['server:start'], () => {
gulp.watch(projects.files.tsFiles, ['server:restart']);
});
gulp.task('migrate:compile:knex', () => {
return gulp.src(`${projects.folders.src}/knexfile.ts`, {
base: projects.folders.src
})
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(tsProject())
.pipe(sourcemaps.write('.', {
includeContent: false,
sourceRoot: () => {
return path.join(__dirname, projects.folders.src);
}
}))
.pipe(gulp.dest(projects.folders.build));
});
gulp.task('migrate:compile:config', () => {
return gulp.src(projects.files.configFiles)
.pipe(plumber())
.pipe(gulp.dest(`${projects.folders.build}/configs`));
});
gulp.task('migrate:compile:script', () => {
return gulp.src([`${projects.folders.migration}/*.ts`, `${projects.folders.src}/libs/constants.ts`, `${projects.folders.src}/data/sql/schema.ts`], {
base: projects.folders.src
})
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(tsProject())
.pipe(sourcemaps.write('.', {
includeContent: false,
sourceRoot: () => {
return path.join(__dirname, projects.folders.migration);
}
}))
.pipe(gulp.dest(projects.folders.build));
});
gulp.task('migrate:compile', (cb) => {
runSequence('clean', 'migrate:compile:knex', 'migrate:compile:script', 'migrate:compile:config', 'files:copy', cb);
});
gulp.task('migrate:new', () => {
if (argv.name != null) {
return file(`${yyyymmddhhmmss()}_${argv.name}.ts`,
`import * as Bluebird from "bluebird";
import * as Knex from "knex";
export const up = (knex: Knex, promise: typeof Bluebird): Bluebird<any> => {
return promise.resolve();
};
export const down = (knex: Knex, promise: typeof Bluebird): Bluebird<any> => {
return promise.resolve();
};`).pipe(gulp.dest(projects.folders.migration));
}
});
gulp.task('migrate:latest', () => {
return;
});
gulp.task('migrate:rollback', () => {
return;
});
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "template-service",
"version": "1.0.0",
"description": "template's backend",
"main": "build/server.js",
"scripts": {
"test": "NODE_ENV=test mocha",
"coverage": "NODE_ENV=test nyc --require ts-node/register ./node_modules/.bin/_mocha",
"migrate": "gulp migrate:new --name",
"prerollback": "gulp migrate:compile",
"prelatest": "gulp migrate:compile",
"rollback": "cd build && ../node_modules/.bin/knex --knexfile knexfile.js migrate:rollback",
"latest": "cd build && ../node_modules/.bin/knex --knexfile knexfile.js migrate:latest",
"clean": "gulp clean"
},
"repository": {
"type": "git",
"url": "git@gitlab.ventuso.net:template/template-service.git"
},
"keywords": [
"rest",
"api"
],
"author": "Bao Nguyen <baond@ventuso.net>",
"license": "ISC",
"devDependencies": {
"@types/bcrypt": "1.0.0",
"@types/bluebird": "3.5.16",
"@types/body-parser": "1.16.5",
"@types/bookshelf": "0.9.1",
"@types/chai": "4.0.4",
"@types/chai-http": "3.0.3",
"@types/compression": "0.0.34",
"@types/dotenv": "4.0.1",
"@types/express": "4.0.37",
"@types/formidable": "1.0.29",
"@types/helmet": "0.0.36",
"@types/js-yaml": "3.9.1",
"@types/jsonwebtoken": "7.2.3",
"@types/knex": "0.0.62",
"@types/kue": "0.11.7",
"@types/lodash": "4.14.77",
"@types/mkdirp": "0.5.1",
"@types/mocha": "2.2.43",
"@types/moment-timezone": "0.5.0",
"@types/node": "8.0.34",
"@types/nodemailer": "3.1.3",
"@types/nodemailer-direct-transport": "1.0.30",
"@types/redis": "2.6.1",
"@types/stack-trace": "0.0.28",
"@types/twilio": "0.0.9",
"@types/uuid": "3.4.2",
"@types/winston": "2.3.6",
"chai": "4.1.2",
"chai-http": "3.0.0",
"gulp": "3.9.1",
"gulp-clean": "0.3.2",
"gulp-develop-server": "0.5.2",
"gulp-file": "0.3.0",
"gulp-istanbul": "1.1.2",
"gulp-json-editor": "2.2.1",
"gulp-plumber": "1.1.0",
"gulp-sourcemaps": "2.6.1",
"gulp-spawn-mocha": "4.0.1",
"gulp-tslint": "8.1.2",
"gulp-typescript": "3.2.2",
"gulp-uglify": "3.0.0",
"gulp-util": "latest",
"gulp-zip": "4.0.0",
"istanbul": "0.4.5",
"mocha": "4.0.1",
"nyc": "11.2.1",
"run-sequence": "2.2.0",
"ts-node": "3.3.0",
"tslint": "5.7.0",
"typescript": "2.5.3"
},
"dependencies": {
"bcrypt": "1.0.3",
"bluebird": "3.5.1",
"body-parser": "1.18.2",
"bookshelf": "0.10.4",
"cities": "1.1.2",
"compression": "1.7.1",
"countryjs": "1.8.0",
"dotenv": "4.0.0",
"express": "4.16.2",
"fcm-node": "1.2.0",
"firebase-admin": "5.4.2",
"formidable": "1.1.1",
"helmet": "3.9.0",
"html-to-text": "3.3.0",
"inversify": "4.3.0",
"js-yaml": "3.10.0",
"jsonwebtoken": "8.1.0",
"knex": "0.13.0",
"kue": "0.11.6",
"kue-scheduler": "0.7.4",
"le_node": "1.7.1",
"lodash": "4.17.4",
"mailgen": "2.0.2",
"mailgun-js": "0.13.1",
"merge2": "1.2.0",
"mkdirp": "0.5.1",
"moment-range": "3.0.3",
"moment-timezone": "0.5.13",
"pg": "7.1.2",
"redis": "2.8.0",
"reflect-metadata": "0.1.10",
"s3-uploader": "2.0.3",
"source-map-support": "0.5.0",
"stack-trace": "0.0.10",
"string-format": "0.5.0",
"stripe": "5.1.1",
"twilio": "3.8.1",
"uuid": "3.1.0",
"wait-on": "2.0.2",
"winston": "2.4.0"
}
}
/**
* Created by phuongho on 15/08/17.
*/
import * as compression from "compression";
import * as express from "express";
import * as helmet from "helmet";
import * as http from "http";
import * as Bluebird from "bluebird";
import * as _ from "lodash";
import Router from "./routes";
import { ExceptionModel } from "./models";
import { ErrorCode, HttpStatus, scheduler as Scheduler } from "./libs";
import { BaseDto } from "./data/sql/models";
import { Database } from "./data/sql/connection";
import { Redis } from "./data/redis/redis";
import { cors, httpError, httpLogger, notFound, recover } from "./middlewares";
import { json, urlencoded } from "body-parser";
interface Log {
error(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
info(message: string, meta?: any): void;
debug(message: string, meta?: any): void;
}
export class Application {
private app: express.Express;
private bind: number;
private server: http.Server;
private logger: Log;
private transportLogger: Log;
constructor(processLogger?: Log, transportLogger?: Log) {
this.logger = processLogger || {
error: (message: string, meta?: any): void => { },
warn: (message: string, meta?: any): void => { },
info: (message: string, meta?: any): void => { },
debug: (message: string, meta?: any): void => { },
};
this.transportLogger = transportLogger || {
error: (message: string, meta?: any): void => { },
warn: (message: string, meta?: any): void => { },
info: (message: string, meta?: any): void => { },
debug: (message: string, meta?: any): void => { },
};
this.app = express();
this.app.locals.title = "iCondo";
this.app.enable("case sensitive routing");
this.app.enable("trust proxy");
this.app.disable("x-powered-by");
this.app.disable("etag");
this.app.use(json());
this.app.use(urlencoded({ extended: false }));
this.app.use(helmet());
this.app.use(compression());
this.app.use(cors());
this.app.use(httpLogger(this.transportLogger));
this.app.use("/", Router);
this.app.use(notFound());
this.app.use(httpError(this.logger));
this.app.use(recover((error: any, res: express.Response): void => {
let err: ExceptionModel;
if (error.httpStatus != null) {
err = error as ExceptionModel;
} else if (error instanceof BaseDto.NotFoundError || BaseDto.NoRowsDeletedError || BaseDto.NoRowsUpdatedError) {
// DB error: BaseDto.NotFoundError, BaseDto.NoRowsDeletedError, BaseDto.NoRowsUpdatedError
err = new ExceptionModel(
ErrorCode.RESOURCE.NOT_FOUND.CODE,
ErrorCode.RESOURCE.NOT_FOUND.MESSAGE,
false,
HttpStatus.NOT_FOUND,
);
} else {
err = ExceptionModel.fromError(ErrorCode.UNKNOWN.GENERIC.CODE, err, true);
}
res.status(err.httpStatus);
err.name = undefined;
err.httpStatus = undefined;
res.json(err);
}));
process.on("unhandledRejection", (reason: any): void => {
this.logger.error("unhandledRejection: " + reason);
});
process.on("uncaughtException", (err: Error): void => {
this.logger.error(err.message, err);
// Note: When this happen, the process should be terminated
// process.exit(1);
});
}
public listen(port: number) {
this.logger.info("Wait for others components become available");
Bluebird.all([
Database.migration(),
// Redis.initWithWaiting(),
// Scheduler.initWithWaiting(),
]).then(() => {
if (process.env.PORT != null) {
this.bind = Application.normalizePort(process.env.PORT);
} else if (port != null) {
this.bind = Application.normalizePort(port);
} else {
this.bind = 3000;
}
this.app.set("port", this.bind);
this.server = http.createServer(this.app);
this.server.on("error", this.onError.bind(this));
this.server.on("listening", this.onListening.bind(this));
this.server.listen(this.bind);
}).catch(err => {
this.logger.error(err.message, err);
});
}
public getExpressInstance(): express.Express {
return this.app;
}
private onListening() {
let addr = this.server.address();
let bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port;
this.logger.info("Listening on " + bind);
}
private onError(error: any) {
if (error.syscall !== "listen") {
throw error;
}
// handle specific listen errors with friendly messages
switch (error.code) {
case "EACCES":
this.logger.error(this.bind + " requires elevated privileges");
process.exit(1);
break;
case "EADDRINUSE":
this.logger.error(this.bind + " is already in use");
process.exit(1);
break;
default:
throw error;
}
}
private static normalizePort(val: any) {
let port = parseInt(val, 10);
if (isNaN(port)) {
return val;
}
if (port >= 0) {
return port;
}
return false;
}
}
export default Application;
port: 3000
database:
postgres:
host: 127.0.0.1
port: 5432
user: postgres
password: postgres
database: vivis
charset: utf8mb4
debug: false
redis:
host: redis
port: 6379
db: "0"
prefix: dev
firebase:
file: firebase.json
database: https://vivis-dev.firebaseio.com
scheduler:
debug: false
prefix: "dev:vivis:scheduler:"
skipConfig: false
restore: true
redis:
host: localhost
port: 6379
db: "0"
mailer:
# Mailgun option
mailGun:
apiKey: <your api key>
domain: <your domain>
sender: <your marketing email>
generator:
name: foobar
link: www.foobar.com
logo: foobar
iOSAppUrl: <your iOS app url>
androidAppUrl: <your andoird app url>
privacyPolicyUrl: <your privacy policy app url>
contactEmail: <your contact email>
session:
expire: 30 # days
whiteList:
- test
log:
# If false, prevent application from exist when something odd happen.
exitOnError: false
# Console logging, use in development only.
console:
level: debug
handleExceptions: true
timestamp: true
json: false
colorize: true
# File logging, file will be put in "logs" folder.
file:
process:
level: debug # Minimum log level which will be appear, Note: error > info > verbose > debug.
name: process.log
maxsize: 5242880
maxFiles: 1
handleExceptions: true
humanReadableUnhandledException: false
json: true
colorize: true
transport:
level: debug # Minimum log level which will be appear, Note: error > info > verbose > debug.
name: transport.log
maxsize: 5242880
maxFiles: 1
handleExceptions: true
humanReadableUnhandledException: false
json: true
colorize: true
logentries:
processToken:
transportToken:
sms:
accountSid: <your sid>
authToken: <your token>
area: "+84"
sender: <your sender>
force: false
sandbox: false
sendEmail: false # if sendEmail == true ==> send email and don't send sms. Server dev will return code for value
payment:
brainTree:
merchantID: <your Merchant ID:>
publicKey: <your public key>
privateKey: <your private Key>
storage:
awsBucketName: ventuso
opts:
aws:
path: images/
region: us-west-2
acl: public-read
accessKeyId: <Your access key here>
secretAccessKey: <Your secret key here>
fcm:
serverKey: <Your FCM key here>
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { ApplicationDto } from "./sql/models";
import { ApplicationModel } from "../models";
import { BaseRepository, Log } from "./base.repository";
import { injectable, inject } from "inversify";
@injectable()
export class ApplicationRepository extends BaseRepository<ApplicationDto, ApplicationModel> {
constructor( @inject("Logger") log?: Log) {
super(ApplicationDto, ApplicationModel, log);
}
}
export default ApplicationRepository;
/**
* Created by Anh Nga on 13/10/2017.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, LanguageModel } from "./../models";
import { ARTICLES_TABLE_SCHEMA } from "./sql/schema";
import { ArticlesDto } from "./sql/models";
import { injectable, inject } from "inversify";
@injectable()
export class ArticlesRepository extends BaseRepository<ArticlesDto, LanguageModel> {
constructor( @inject("Logger") log?: Log) {
super(ArticlesDto, LanguageModel, log);
}
/**
* search language
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<LanguageModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.where(`${Schema.LANGUAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.LANGUAGE_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.LANGUAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.LANGUAGE_TABLE_SCHEMA.FIELDS.NAME}`, "ILIKE", `%${keyword}%`);
});
}
let orderBy = searchParams.orderBy || `${Schema.LANGUAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.LANGUAGE_TABLE_SCHEMA.FIELDS.PRIORITY}`;
let orderType = searchParams.orderType || "DESC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default ArticlesRepository;
import { Log } from "./../libs/logger";
import { ASSIGN_PRESENTATION_TABLE_SCHEMA } from "./sql/schema";
import { CollectionWrap } from "./../models/collections";
import { BaseRepository } from "./base.repository";
import { AssignPresentationDto } from "./sql/models";
import { AssignPresentationModel } from "../models";
import * as Schema from "../data/sql/schema";
import * as Promise from "bluebird";
import { injectable, inject } from "inversify";
@injectable()
export class AssignPresentationRepository extends BaseRepository<AssignPresentationDto, AssignPresentationModel> {
constructor( @inject("Logger") log?: Log) {
super(AssignPresentationDto, AssignPresentationModel, log);
}
}
export default AssignPresentationRepository;
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as _ from "lodash";
import { BaseDto } from "./sql/models";
import { BaseModel, CollectionWrap, ExceptionModel } from "../models";
import { BookshelfMapper } from "./../libs/mapper/bookshelf.mapper";
import { ErrorCode, HttpStatus } from "../libs";
import { QueryBuilder } from "knex";
import { WithRelatedQuery, ModelBase } from "bookshelf";
export interface Log {
error(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
info(message: string, meta?: any): void;
debug(message: string, meta?: any): void;
}
// export interface Repository<M> {
// update(model: M): Promise<any>;
// insert(model: M): Promise<any>;
// insertGet(insertGet: M, related: string[], filters: string[]): Promise<M>;
// forceDelete(id: String): Promise<boolean>;
// }
import { injectable, unmanaged } from "inversify";
@injectable()
export class BaseRepository<T extends BaseDto<T>, X extends BaseModel> {
constructor( @unmanaged() protected dto: { new (attributes?: any, isNew?: boolean): T },
@unmanaged() protected model: { new (): X },
protected logger?: Log) {
this.logger = logger || {
error: (message: string, meta?: any): void => { },
warn: (message: string, meta?: any): void => { },
info: (message: string, meta?: any): void => { },
debug: (message: string, meta?: any): void => { },
};
}
/**
*
* @param model
*/
public update(model: X): Bluebird<T> {
if (model == null && model.id != null && model.id !== "") {
return Bluebird.reject(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST
));
}
let data = BookshelfMapper.serialize(model);
return new this.dto({ id: data.id }).save(data, {
patch: true
});
}
/**
*
* @param model
*/
public insert(model: X): Bluebird<T> {
if (model == null) {
return Bluebird.resolve(null);
}
let data = BookshelfMapper.serialize(model);
return new this.dto().save(data);
}
/**
* Function insert and convert to model object with related and filters.
*
* @param model
* @param related
* @param filters
* @returns {Bluebird<U>}
*/
public insertGet(model: X, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<X> {
return this.insert(model)
.then(result => {
return this.findById(result.id, related, filters);
});
}
/**
*
* @param id
*/
public forceDelete(id: string): Bluebird<boolean> {
if (id == null) {
return Bluebird.resolve(false);
}
return new this.dto({ id: id }).destroy()
.then(() => {
return true;
})
.catch(err => {
this.logger.error(err.message, err);
return false;
});
}
/**
*
* @param id
*/
public deleteLogic(id: string): Bluebird<T> {
if (id == null || id.length === 0) {
return Bluebird.reject(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST
));
}
return this.findById(id)
.then((object) => {
if (!object) {
throw new ExceptionModel(
ErrorCode.RESOURCE.NOT_FOUND.CODE,
ErrorCode.RESOURCE.NOT_FOUND.MESSAGE,
false,
HttpStatus.BAD_REQUEST
);
}
return new this.dto({ id: id }).save({ is_deleted: 1 }, { patch: true });
});
}
/**
*
* @param callback
* @returns {BlueBird<any>}
*/
public deleteByQuery(callback: (qb: QueryBuilder) => void): Bluebird<any[]> {
return new this.dto().query(callback).destroy();
}
/**
*
* @returns {BlueBird<any>}
*/
public truncate(): any {
return new this.dto().query().truncate();
}
/**
*
* @param callback
* @returns {BlueBird<any>}
*/
public updateByQuery(callback: (qb: QueryBuilder) => void, model: any): Bluebird<T> {
return new this.dto({}, false).query(callback).save(model, {
method: "update",
patch: true,
require: false
});
}
/**
*
* @param ids
* @param related
* @param filters
*/
public findAll(ids: string[], related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<X[]> {
if (ids == null || ids.length === 0) {
return Bluebird.resolve([]);
}
let dto = new this.dto();
return dto.query((q): void => {
q.whereIn(dto.idAttribute, ids);
q.where(dto.isDelete, false);
})
.fetchAll({ withRelated: related })
.then((objects) => {
let ret: X[] = [];
if (objects != null && objects.models != null && _.isArray(objects.models)) {
objects.models.forEach(object => {
let model = BookshelfMapper.deserialize(this.model, object);
BaseModel.filters(model, filters);
if (model != null) {
ret.push(model);
}
});
}
return ret;
});
}
/**
*
* @param ids
* @param offset
* @param limit
* @param related
* @param filters
*/
public findAllByPage(ids: string[] = [], offset: number = 0, limit: number = 50, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<CollectionWrap<X>> {
let ret = new CollectionWrap<X>();
let dto = new this.dto();
return dto.query((q): void => {
if (ids.length > 0) {
q.whereIn(dto.idAttribute, ids);
}
q.where(dto.isDelete, false);
}).fetchPage({ limit: limit, offset: 0, withRelated: related })
.then((rows) => {
if (rows != null && rows.models != null && _.isArray(rows.models)) {
rows.models.forEach((dtoObject: T) => {
let item = BookshelfMapper.deserialize(this.model, dtoObject);
BaseModel.filters(item, filters);
ret.data.push(item);
});
if (rows.pagination != null) {
ret.total = rows.pagination.rowCount;
}
}
return ret;
})
.catch((err: Error) => {
return ret;
});
}
/**
*
* @param id
* @param related
* @param filters
*/
public findOne(id: string, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<X> {
let ret: X = null;
if (id == null || id === "") {
return Bluebird.resolve(ret);
}
return this.findById(id, related, filters);
}
/**
*
* @param id
* @param related
* @param filters
*/
public findById(id: string, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<X> {
let ret: X = null;
if (id == null || id === "") {
return Bluebird.resolve(ret);
}
return new this.dto().where({ id: id }).fetch({ withRelated: related })
.then((object) => {
if (object) {
let temp = BookshelfMapper.deserialize(this.model, object);
BaseModel.filters(temp, filters);
return temp;
}
return null;
});
}
/**
*
* @param callback
*/
public countByQuery(callback: (qb: QueryBuilder) => void): Bluebird<number> {
if (callback == null) {
return Bluebird.resolve(0);
}
return new this.dto().query(callback).count()
.then((total) => {
return Number(total);
});
}
/**
*
* @param callback
* @param related
* @param filters
*/
public findByQuery(callback: (qb: QueryBuilder) => void, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<X[]> {
return new this.dto().query(callback).fetchAll({ withRelated: related })
.then(items => {
let ret: X[] = [];
if (items != null && _.isArray(items.models))
items.models.forEach(item => {
let temp = BookshelfMapper.deserialize(this.model, item);
BaseModel.filters(temp, filters);
if (temp != null) {
ret.push(temp);
}
});
return ret;
})
.catch(err => {
this.logger.error(err.message, err);
return [];
});
}
/**
*
* @param callback
* @param related
* @param filters
*/
public findOneByQuery(callback: (qb: QueryBuilder) => void, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<X> {
return new this.dto().query(callback).fetch({ withRelated: related })
.then(item => {
if (item != null) {
let data = BookshelfMapper.deserialize(this.model, item);
BaseModel.filters(data, filters);
return data;
}
return null;
});
}
public countAndQuery(countQuery: (qb: QueryBuilder) => void, findQuery: (qb: QueryBuilder) => void, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<CollectionWrap<X>> {
let ret = new CollectionWrap<X>();
return this.countByQuery(countQuery)
.then((total) => {
ret.total = total;
return this.findByQuery(findQuery, related, filters);
})
.then((objects) => {
ret.data = objects;
return ret;
});
}
/**
*
* @param query
*/
public raw(query: string): Knex.Raw {
return BaseDto.knex().raw(query);
}
/**
*
* @param query
*/
public rawQuery(query: string) {
return BaseDto.knex().raw(query).then(result => {
return result.rows;
});
}
/**
*
* @param callback
* @param offset
* @param limit
* @param related
* @param filters
*/
public queryByPage(callback: (qb: QueryBuilder) => void, offset: number = 0, limit: number = 50, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<CollectionWrap<X>> {
let ret = new CollectionWrap<X>();
if (callback == null) {
return Bluebird.resolve(ret);
}
let dto = new this.dto();
return dto.query(callback).fetchPage({ limit: limit, offset: offset, withRelated: related })
.then((rows) => {
if (rows != null && rows.models != null && _.isArray(rows.models)) {
rows.models.forEach((dtoObject: T) => {
let item = BookshelfMapper.deserialize(this.model, dtoObject);
BaseModel.filters(item, filters);
ret.data.push(item);
});
if (rows.pagination != null) {
ret.total = rows.pagination.rowCount;
}
}
return ret;
})
.catch((err: Error) => {
this.logger.error(err.message, err);
return ret;
});
}
/**
*
* @param callback
* @param related
* @param filters
*/
public query(callback: (qb: QueryBuilder) => void, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<X[]> {
let ret = [];
if (callback == null) {
return Bluebird.resolve(ret);
}
let dto = new this.dto();
return dto.query(callback).fetchAll()
.then((rows) => {
if (rows != null && rows.models != null && _.isArray(rows.models)) {
rows.models.forEach((dtoObject: T) => {
let item = BookshelfMapper.deserialize(this.model, dtoObject);
BaseModel.filters(item, filters);
ret.push(item);
});
}
return ret;
})
.catch((err: Error) => {
return ret;
});
}
/**
*
* @param options {conditions: String|Object; orderBy: String|Object; groupBy: String}
* @param related
* @param filters
*/
public findOneByAtribute(options: any, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<X> {
return Bluebird.resolve()
.then(() => {
let query = () => {
return (q): void => {
if (options.conditions) {
if (_.isObject(options.conditions)) {
_.forOwn(options.conditions, (value, attribute) => {
q.where(attribute, value);
});
}
if (_.isString(options.conditions)) {
q.whereRaw(options.conditions);
}
}
if (options.orderBy) {
if (_.isObject(options.orderBy)) {
_.forOwn(options.orderBy, (value, attribute) => {
q.orderBy(attribute, value);
});
}
if (_.isString(options.conditions)) {
q.orderByRaw(options.orderBy);
}
}
if (options.groupBy) {
q.groupByRaw(options.groupBy);
}
};
};
return this.findOneByQuery(query(), related, filters);
});
}
/**
*
* @param options {conditions: String|Object; orderBy: String|Object; groupBy: String}
* @param related
* @param filters
*/
public findAllByAtribute(options: any, offset?: number, limit?: number, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Bluebird<CollectionWrap<X>> {
return Bluebird.resolve()
.then(() => {
let query = () => {
return (q): void => {
if (options.conditions) {
if (_.isObject(options.conditions)) {
_.forOwn(options.conditions, (value, attribute) => {
q.where(attribute, value);
});
}
if (_.isString(options.conditions)) {
q.whereRaw(options.conditions);
}
}
if (options.orderBy) {
if (_.isObject(options.orderBy)) {
_.forOwn(options.orderBy, (value, attribute) => {
q.orderBy(attribute, value);
});
}
if (_.isString(options.conditions)) {
q.orderByRaw(options.orderBy);
}
}
if (options.groupBy) {
q.groupByRaw(options.groupBy);
}
};
};
return this.queryByPage(query(), offset, limit, related, filters);
});
}
}
export default BaseRepository;
/**
* Created by Anh Nga on 13/10/2017.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, CategoryModel } from "./../models";
import { CATEGORY_TABLE_SCHEMA } from "./sql/schema";
import { CategoryDto } from "./sql/models";
import { injectable, inject } from "inversify";
@injectable()
export class CategoryRepository extends BaseRepository<CategoryDto, CategoryModel> {
constructor( @inject("Logger") log?: Log) {
super(CategoryDto, CategoryModel, log);
}
/**
* search category
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<CategoryModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.where(`${Schema.CATEGORY_TABLE_SCHEMA.TABLE_NAME}.${Schema.CATEGORY_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.CATEGORY_TABLE_SCHEMA.TABLE_NAME}.${Schema.CATEGORY_TABLE_SCHEMA.FIELDS.NAME}`, "ILIKE", `%${keyword}%`);
});
}
let orderBy = searchParams.orderBy || `${Schema.CATEGORY_TABLE_SCHEMA.TABLE_NAME}.${Schema.CATEGORY_TABLE_SCHEMA.FIELDS.ID}`;
let orderType = searchParams.orderType || "DESC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default CategoryRepository;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { DeviceDto } from "./sql/models";
import { DeviceModel } from "../models";
import { injectable, inject } from "inversify";
@injectable()
export class DeviceRepository extends BaseRepository<DeviceDto, DeviceModel> {
constructor( @inject("Logger") log?: Log) {
super(DeviceDto, DeviceModel, log);
}
public findByUserId(userId: string, related = [], filters = []): Promise<DeviceModel> {
return this.findOneByQuery(q => {
q.where(Schema.DEVICE_TABLE_SCHEMA.FIELDS.USER_ID, userId);
}, related, filters);
}
public findByDeviceId(deviceId: string, related = [], filters = []): Promise<DeviceModel> {
return this.findOneByQuery(q => {
q.where(Schema.DEVICE_TABLE_SCHEMA.FIELDS.DEVICE_ID, deviceId);
}, related, filters);
}
public getDevicesByUserId(userId: string): Promise<DeviceModel[]> {
if (userId == null || userId === "") {
return Promise.resolve([]);
}
return this.findByQuery(q => {
q.where(Schema.DEVICE_TABLE_SCHEMA.FIELDS.USER_ID, userId);
}, ["user"]);
}
}
export default DeviceRepository;
/**
* Created by phuongho on 15/08/17.
*/
import { logger } from "../libs";
import { ApplicationRepository } from "./application.repository";
import { DeviceRepository } from "./device.repository";
import { MediaRepository } from "./media.repository";
import { PackageRepository } from "./package.repository";
import { PresentationRepository } from "./presentation.repository";
import { RoleRepository } from "./role.repository";
import { SessionRepository } from "./session.repository";
import { SettingRepository } from "./setting.repository";
import { TagRepository } from "./tag.repository";
import { UserPackageRepository } from "./user_package.repository";
import { UserPresentationRepository } from "./user_presentation.repository";
import { AssignPresentationRepository } from "./assign_presentation.repository";
import { UserCodeRepository } from "./user_code.repository";
import { UserRepository } from "./user.repository";
import { UserTagRepository } from "./user_tag.repository";
import { LanguageRepository } from "./language.respository";
import { CategoryRepository } from "./category.respository";
import { ArticlesRepository } from "./articles.respository";
export { ApplicationRepository } from "./application.repository";
export { BaseRepository } from "./base.repository";
export { DeviceRepository } from "./device.repository";
export { MediaRepository } from "./media.repository";
export { PackageRepository } from "./package.repository";
export { PresentationRepository } from "./presentation.repository";
export { RoleRepository } from "./role.repository";
export { SessionRepository } from "./session.repository";
export { SettingRepository } from "./setting.repository";
export { TagRepository } from "./tag.repository";
export { UserPackageRepository } from "./user_package.repository";
export { UserPresentationRepository } from "./user_presentation.repository";
export { AssignPresentationRepository } from "./assign_presentation.repository";
export { UserCodeRepository } from "./user_code.repository";
export { UserRepository } from "./user.repository";
export { UserTagRepository } from "./user_tag.repository";
export { LanguageRepository } from "./language.respository";
export { CategoryRepository } from "./category.respository";
export { ArticlesRepository } from "./articles.respository";
/**
* Created by Anh Nga on 13/10/2017.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, LanguageModel } from "./../models";
import { LANGUAGE_TABLE_SCHEMA } from "./sql/schema";
import { LanguageDto } from "./sql/models";
import { injectable, inject } from "inversify";
@injectable()
export class LanguageRepository extends BaseRepository<LanguageDto, LanguageModel> {
constructor( @inject("Logger") log?: Log) {
super(LanguageDto, LanguageModel, log);
}
/**
* search language
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<LanguageModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.where(`${Schema.LANGUAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.LANGUAGE_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.LANGUAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.LANGUAGE_TABLE_SCHEMA.FIELDS.NAME}`, "ILIKE", `%${keyword}%`);
});
}
let orderBy = searchParams.orderBy || `${Schema.LANGUAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.LANGUAGE_TABLE_SCHEMA.FIELDS.PRIORITY}`;
let orderType = searchParams.orderType || "DESC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default LanguageRepository;
/**
* Created by phuongho on 15/08/17.
*/
import { BaseRepository, Log } from "./base.repository";
import { MediaDto } from "./sql/models";
import { MediaModel } from "../models";
import { injectable, inject } from "inversify";
@injectable()
export class MediaRepository extends BaseRepository<MediaDto, MediaModel> {
constructor( @inject("Logger") log?: Log) {
super(MediaDto, MediaModel, log);
}
}
export default MediaRepository;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, PackageModel } from "./../models";
import { PACKAGE_TABLE_SCHEMA } from "./sql/schema";
import { PackageDto } from "./sql/models";
import { injectable, inject } from "inversify";
@injectable()
export class PackageRepository extends BaseRepository<PackageDto, PackageModel> {
constructor( @inject("Logger") log?: Log) {
super(PackageDto, PackageModel, log);
}
/**
* search Package
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<PackageModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.where(`${Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.PACKAGE_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.PACKAGE_TABLE_SCHEMA.FIELDS.NAME}`, "ILIKE", `%${keyword}%`);
});
}
let orderBy = searchParams.orderBy || `${Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.PACKAGE_TABLE_SCHEMA.FIELDS.PRIORITY}`;
let orderType = searchParams.orderType || "ASC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default PackageRepository;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, PresentationModel } from "./../models";
import { PRESENTATION_TABLE_SCHEMA } from "./sql/schema";
import { PresentationDto } from "./sql/models";
import { ROLE } from "./../libs/constants";
import { injectable, inject } from "inversify";
@injectable()
export class PresentationRepository extends BaseRepository<PresentationDto, PresentationModel> {
constructor( @inject("Logger") log?: Log) {
super(PresentationDto, PresentationModel, log);
}
/**
* search Presentation
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<PresentationModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
if (searchParams.roleId === ROLE.PRESENTER) {
q.leftJoin(`${Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME}`, `${Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.PRESENTATION_ID}`, `${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.ID}`);
q.where(`${Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
q.where(`${Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.USER_ID}`, searchParams.userId);
} else {
if (searchParams.userId) {
q.where(`${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.USER_ID}`, searchParams.userId);
}
}
q.where(`${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.TITLE}`, "ILIKE", `%${keyword}%`);
});
}
let orderBy = searchParams.orderBy || `${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.PRIORITY}`;
let orderType = searchParams.orderType || "ASC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default PresentationRepository;
import * as Bluebird from "bluebird";
import {ClientOpts, Multi, RedisClient} from "redis";
import * as _ from "lodash";
import {config as Configuration, logger as Logger, Utils} from "../../libs";
const waitOn = require("wait-on");
const RedisLib = require("redis");
Bluebird.promisifyAll(RedisLib.Multi.prototype);
Bluebird.promisifyAll(RedisLib.RedisClient.prototype);
declare module "redis" {
export interface Multi extends NodeJS.EventEmitter {
constructor();
execAsync(...args: any[]): Bluebird<any>;
}
export interface RedisClient extends NodeJS.EventEmitter {
decrAsync(...args: any[]): Bluebird<any>;
delAsync(...args: any[]): Bluebird<any>;
execAsync(...args: any[]): Bluebird<any>;
getAsync(...args: any[]): Bluebird<any>;
incrAsync(...args: any[]): Bluebird<any>;
expireAsync(...args: any[]): Bluebird<any>;
saddAsync(...args: any[]): Bluebird<any>;
scardAsync(...args: any[]): Bluebird<any>;
sdiffAsync(...args: any[]): Bluebird<any>;
sdiffstoreAsync(...args: any[]): Bluebird<any>;
setAsync(...args: any[]): Bluebird<any>;
sinterAsync(...args: any[]): Bluebird<any>;
sismemberAsync(...args: any[]): Bluebird<any>;
smembersAsync(...args: any[]): Bluebird<any>;
smoveAsync(...args: any[]): Bluebird<any>;
spopAsync(...args: any[]): Bluebird<any>;
srandmemeberAsync(...args: any[]): Bluebird<any>;
sremAsync(...args: any[]): Bluebird<any>;
sscanAsync(...args: any[]): Bluebird<any>;
sunionAsync(...args: any[]): Bluebird<any>;
sunionstoreAsync(...args: any[]): Bluebird<any>;
}
}
interface RedisOpts extends ClientOpts {
prefix: string;
}
export class RedisConnection {
private opts: RedisOpts;
private client: RedisClient;
constructor(opts?: any) {
opts = opts || {};
let defaultOpts: RedisOpts = {
host: "localhost",
port: 6379,
db: "1",
prefix: process.env.NODE_ENV + ":template:service:v1:",
};
this.opts = _.defaultsDeep(opts, defaultOpts) as RedisOpts;
}
public initWithWaiting(): Bluebird<boolean> {
if (process.env.NODE_ENV === "test") {
return Bluebird.resolve(true);
}
Logger.info("Wait for redis connection");
let isComplete = false;
return Utils.PromiseLoop(
() => {
return isComplete === true;
},
() => {
return new Bluebird((resolve, reject) => {
waitOn({
resources: [`tcp:${this.opts.host}:${this.opts.port}`]
}, (err) => {
if (err != null) {
reject(err);
} else {
resolve();
}
});
}).then(() => {
this.client = Bluebird.promisifyAll(RedisLib.createClient(this.opts)) as RedisClient;
Logger.info("Redis connection is OK");
isComplete = true;
}).catch((err) => {
Logger.info("Connect to redis failed, try again");
Logger.error(err.message);
isComplete = false;
});
})
.then((object) => {
return isComplete;
});
}
/**
*
* @returns {RedisClient}
*/
public getClient(): RedisClient {
return this.client;
}
}
export const Redis = new RedisConnection(Configuration.database != null ? Configuration.database.redis : null);
export default Redis;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, RoleModel } from "./../models";
import { ROLE } from "./../libs/constants";
import { RoleDto } from "./sql/models";
import { injectable, inject } from "inversify";
@injectable()
export class RoleRepository extends BaseRepository<RoleDto, RoleModel> {
constructor( @inject("Logger") log?: Log) {
super(RoleDto, RoleModel, log);
}
/**
* search role
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<RoleModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.where(`${Schema.ROLE_TABLE_SCHEMA.TABLE_NAME}.${Schema.ROLE_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.ROLE_TABLE_SCHEMA.TABLE_NAME}.${Schema.ROLE_TABLE_SCHEMA.FIELDS.NAME}`, "ILIKE", `%${keyword}%`);
});
}
if (searchParams.roleId === ROLE.MANAGER) {
q.whereNotIn(`${Schema.ROLE_TABLE_SCHEMA.TABLE_NAME}.${Schema.ROLE_TABLE_SCHEMA.FIELDS.ID}`, [ROLE.SYSTEM_ADMIN, ROLE.MANAGER]);
}
if (searchParams.roleId === ROLE.COMPANY_ADMIN) {
q.whereNotIn(`${Schema.ROLE_TABLE_SCHEMA.TABLE_NAME}.${Schema.ROLE_TABLE_SCHEMA.FIELDS.ID}`, [ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]);
}
let orderBy = searchParams.orderBy || `${Schema.ROLE_TABLE_SCHEMA.TABLE_NAME}.${Schema.ROLE_TABLE_SCHEMA.FIELDS.CREATED_DATE}`;
let orderType = searchParams.orderType || "DESC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default RoleRepository;
/**
* Created by phuongho on 15/08/17.
*/
import { BaseRepository, Log } from "./base.repository";
import { SessionDto } from "./sql/models";
import { SessionModel } from "../models";
import { injectable, inject } from "inversify";
@injectable()
export class SessionRepository extends BaseRepository<SessionDto, SessionModel> {
constructor( @inject("Logger") log?: Log) {
super(SessionDto, SessionModel, log);
}
}
export default SessionRepository;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, SettingModel } from "./../models";
import { SETTING_TABLE_SCHEMA } from "./sql/schema";
import { SettingDto } from "./sql/models";
import { injectable, inject } from "inversify";
@injectable()
export class SettingRepository extends BaseRepository<SettingDto, SettingModel> {
constructor( @inject("Logger") log?: Log) {
super(SettingDto, SettingModel, log);
}
/**
* search Setting
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<SettingModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.where(`${Schema.SETTING_TABLE_SCHEMA.TABLE_NAME}.${Schema.SETTING_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.SETTING_TABLE_SCHEMA.TABLE_NAME}.${Schema.SETTING_TABLE_SCHEMA.FIELDS.KEYWORD}`, "ILIKE", `%${keyword}%`);
});
}
let orderBy = searchParams.orderBy || `${Schema.SETTING_TABLE_SCHEMA.TABLE_NAME}.${Schema.SETTING_TABLE_SCHEMA.FIELDS.CREATED_DATE}`;
let orderType = searchParams.orderType || "DESC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default SettingRepository;
/**
* Created by phuongho on 15/08/17.
*/
import * as Bluebird from "bluebird";
import * as Bookshelf from "bookshelf";
import * as Knex from "knex";
import * as _ from "lodash";
import * as waitOn from "wait-on";
import { config, logger, Utils } from "../../libs";
import { MySqlConnectionConfig } from "knex";
declare module "bookshelf" {
interface Bookshelf extends Bookshelf.Events<any> {
model(name: String, model: Model<any>): Model<any>;
}
interface ModelBase<T extends Model<any>> extends IModelBase { }
interface Model<T extends Model<any>> extends ModelBase<T> {
// For pagination plugin
fetchPage(options?: { limit; number, offset: number, withRelated: WithRelatedQuery });
// For registry plugin
belongsTo<R extends Model<any>>(target: { new (...args: any[]): R } | String, foreignKey?: string, foreignKeyTarget?: string): R;
hasMany<R extends Model<any>>(target: { new (...args: any[]): R } | String, foreignKey?: string, foreignKeyTarget?: string): Collection<R>;
hasOne<R extends Model<any>>(target: { new (...args: any[]): R } | String, foreignKey?: string, foreignKeyTarget?: string): R;
belongsToMany<R extends Model<any>>(target: { new (...args: any[]): R } | String, table?: string, foreignKey?: string, otherKey?: string, foreignKeyTarget?: string, otherKeyTarget?: string): Collection<R>;
}
}
interface Log {
error(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
info(message: string, meta?: any): void;
debug(message: string, meta?: any): void;
}
export class Connection {
private sql: MySqlConnectionConfig;
private instance: Bookshelf;
constructor(opts?: any, private logger?: Log) {
this.logger = logger || {
error: (message: string, meta?: any): void => { },
warn: (message: string, meta?: any): void => { },
info: (message: string, meta?: any): void => { },
debug: (message: string, meta?: any): void => { },
};
opts = opts || {};
let defaultConf: MySqlConnectionConfig = {
host: "127.0.0.1",
port: 5432,
user: "root",
password: "",
database: "test",
charset: "utf8mb4",
timezone: "UTC",
};
this.sql = _.defaultsDeep(opts, defaultConf) as MySqlConnectionConfig;
if (process.env.DB_HOST != null) {
this.sql.host = process.env.DB_HOST;
}
if (process.env.DB_PORT != null) {
this.sql.port = Number.parseInt(process.env.DB_PORT, 10);
}
if (process.env.DB_USER != null) {
this.sql.user = process.env.DB_USER;
}
if (process.env.DB_PASSWORD != null) {
this.sql.password = process.env.DB_PASSWORD;
}
if (process.env.DB_NAME != null) {
this.sql.database = process.env.DB_NAME;
}
let knex: Knex = Knex({
client: "postgresql",
connection: this.sql,
debug: this.sql.debug ? this.sql.debug : false,
});
this.instance = Bookshelf(knex);
this.instance.plugin("pagination");
this.instance.plugin("registry");
}
public migration(): Bluebird<boolean> {
this.logger.info("Wait for database connection");
let isComplete = false;
return Utils.PromiseLoop(
() => {
return isComplete === true;
},
() => {
return new Bluebird((resolve, reject) => {
waitOn({
resources: [`tcp:${this.sql.host}:${this.sql.port}`]
}, (err) => {
if (err != null) {
reject(err);
} else {
resolve();
}
});
}).then(() => {
return Bluebird.delay(1000);
}).then(() => {
this.logger.info("Perform database migration");
return this.instance.knex.migrate.latest({
directory: __dirname + "/migrations",
});
}).then((info) => {
this.logger.info("All migrations were success");
isComplete = true;
}).catch((err) => {
this.logger.info("All migrations were failed, try again");
this.logger.error(err.message);
isComplete = false;
});
})
.then((object) => {
return isComplete;
});
}
public bookshelf(): Bookshelf {
return this.instance;
}
}
export const Database = new Connection(config.database ? config.database.postgres : {}, logger);
export default Database;
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
/**
* Create setting table and its default data
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const setting = (knex: Knex, Promise: typeof Bluebird) => {
// create setting table;
let SCHEMA = Schema.SETTING_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.boolean(SCHEMA.FIELDS.IS_ENABLE).notNullable().defaultTo(1);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.KEYWORD, 100).notNullable().unique();
table.string(SCHEMA.FIELDS.VALUE, 100).notNullable();
table.string(SCHEMA.FIELDS.DESC, 255).notNullable();
});
});
};
/**
* Create roles table and its default data
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const role = (knex: Knex, Promise: typeof Bluebird) => {
// create role table;
let SCHEMA = Schema.ROLE_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.NAME, 255).notNullable();
table.text(SCHEMA.FIELDS.DESCRIPTION).nullable();
});
})
.then(() => {
let systemAdmin = {};
systemAdmin[SCHEMA.FIELDS.ID] = "system_admin";
systemAdmin[SCHEMA.FIELDS.NAME] = "System Admin";
systemAdmin[SCHEMA.FIELDS.DESCRIPTION] = "System Admin";
let manager = {};
manager[Schema.ROLE_TABLE_SCHEMA.FIELDS.ID] = "manager";
manager[Schema.ROLE_TABLE_SCHEMA.FIELDS.NAME] = "Manager";
manager[Schema.ROLE_TABLE_SCHEMA.FIELDS.DESCRIPTION] = "Manager Admin";
let companyAdmin = {};
companyAdmin[Schema.ROLE_TABLE_SCHEMA.FIELDS.ID] = "company_admin";
companyAdmin[Schema.ROLE_TABLE_SCHEMA.FIELDS.NAME] = "Company Admin";
companyAdmin[Schema.ROLE_TABLE_SCHEMA.FIELDS.DESCRIPTION] = "Company Admin";
let operator = {};
operator[Schema.ROLE_TABLE_SCHEMA.FIELDS.ID] = "operator";
operator[Schema.ROLE_TABLE_SCHEMA.FIELDS.NAME] = "Operator";
operator[Schema.ROLE_TABLE_SCHEMA.FIELDS.DESCRIPTION] = "Operator";
let presenter = {};
presenter[Schema.ROLE_TABLE_SCHEMA.FIELDS.ID] = "presenter";
presenter[Schema.ROLE_TABLE_SCHEMA.FIELDS.NAME] = "Presenter";
presenter[Schema.ROLE_TABLE_SCHEMA.FIELDS.DESCRIPTION] = "Presenter";
return Promise.all([
// Inserts seed entries
knex(SCHEMA.TABLE_NAME).insert(systemAdmin),
knex(SCHEMA.TABLE_NAME).insert(manager),
knex(SCHEMA.TABLE_NAME).insert(companyAdmin),
knex(SCHEMA.TABLE_NAME).insert(operator),
knex(SCHEMA.TABLE_NAME).insert(presenter)
]);
});
};
/**
* Create users table and its default data
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const user = (knex, Promise) => {
let SCHEMA = Schema.USER_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.ROLE_ID, 36).notNullable().index()
.references(Schema.ROLE_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.ROLE_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.EMAIL, 100).notNullable();
table.string(SCHEMA.FIELDS.PASSWORD, 255).nullable();
table.string(SCHEMA.FIELDS.FIRST_NAME, 255).notNullable();
table.string(SCHEMA.FIELDS.LAST_NAME, 255).notNullable();
table.string(SCHEMA.FIELDS.PHONE_NUMBER, 255).nullable();
table.text(SCHEMA.FIELDS.AVATAR_URL).nullable();
});
})
.then(() => {
let systemAdmin = {};
systemAdmin[SCHEMA.FIELDS.ID] = UUID();
systemAdmin[SCHEMA.FIELDS.ROLE_ID] = "system_admin";
systemAdmin[SCHEMA.FIELDS.EMAIL] = "admin@ventuso.net";
systemAdmin[SCHEMA.FIELDS.PASSWORD] = "$2a$10$Wi0mafgo9CnGYd.gK90ZXe5cgEAM0GyzjDsjm63Fq5t0c8su8.6ni";
systemAdmin[SCHEMA.FIELDS.FIRST_NAME] = "Admin";
systemAdmin[SCHEMA.FIELDS.LAST_NAME] = "System";
let manager = {};
manager[SCHEMA.FIELDS.ID] = UUID();
manager[SCHEMA.FIELDS.ROLE_ID] = "manager";
manager[SCHEMA.FIELDS.EMAIL] = "manager@ventuso.net";
manager[SCHEMA.FIELDS.PASSWORD] = "$2a$10$Wi0mafgo9CnGYd.gK90ZXe5cgEAM0GyzjDsjm63Fq5t0c8su8.6ni";
manager[SCHEMA.FIELDS.FIRST_NAME] = "Admin";
manager[SCHEMA.FIELDS.LAST_NAME] = "Manager";
return Promise.all([
// Inserts seed entries
knex(SCHEMA.TABLE_NAME).insert(systemAdmin),
knex(SCHEMA.TABLE_NAME).insert(manager)
]);
});
};
/**
* Create sessions table and its default data
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const sessions = (knex, Promise) => {
// create sessions table;
let SCHEMA = Schema.SESSION_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.text(SCHEMA.FIELDS.TOKEN).notNullable();
table.dateTime(SCHEMA.FIELDS.EXPIRE).notNullable();
table.string(SCHEMA.FIELDS.HASH, 36).notNullable();
table.string(SCHEMA.FIELDS.USER_ID, 36).notNullable().index()
.references(Schema.USER_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.USER_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
});
});
};
/**
* Create devices table and its default data
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const devices = (knex, Promise) => {
// create setting table;
let SCHEMA = Schema.DEVICE_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.string(SCHEMA.FIELDS.USER_ID, 36).notNullable().index()
.references(Schema.USER_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.USER_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.DEVICE_ID, 255).notNullable();
table.string(SCHEMA.FIELDS.REGISTRAR_ID, 255).notNullable().defaultTo("");
table.string(SCHEMA.FIELDS.DEVICE_OS, 255).nullable();
table.string(SCHEMA.FIELDS.DEVICE_MODEL, 255).nullable();
table.string(SCHEMA.FIELDS.BUILD_VERSION, 255).nullable();
table.string(SCHEMA.FIELDS.DEVICE_NAME, 255).nullable();
table.string(SCHEMA.FIELDS.OS_VERSION, 255).nullable();
table.string(SCHEMA.FIELDS.APP_VERSION, 255).nullable();
table.integer(SCHEMA.FIELDS.IS_SANDBOX).notNullable().defaultTo(1);
});
});
};
/**
* Create application table and its default data
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const applications = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return knex.schema.createTable(Schema.APPLICATION_TABLE_SCHEMA.TABLE_NAME, (table => {
table.string(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.PLATFORM).notNullable().defaultTo(PLATFORM.IOS);
table.integer(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.VERSION).notNullable().defaultTo(100);
table.boolean(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.IS_LATEST).notNullable().defaultTo(1);
table.boolean(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.FORCE_UPDATE).notNullable().defaultTo(0);
}));
})
.then(() => {
let ios = {};
ios[Schema.APPLICATION_TABLE_SCHEMA.FIELDS.ID] = UUID();
ios[Schema.APPLICATION_TABLE_SCHEMA.FIELDS.PLATFORM] = PLATFORM.IOS;
ios[Schema.APPLICATION_TABLE_SCHEMA.FIELDS.VERSION] = 1;
ios[Schema.APPLICATION_TABLE_SCHEMA.FIELDS.IS_LATEST] = true;
ios[Schema.APPLICATION_TABLE_SCHEMA.FIELDS.FORCE_UPDATE] = false;
let android = {};
android[Schema.APPLICATION_TABLE_SCHEMA.FIELDS.ID] = UUID();
android[Schema.APPLICATION_TABLE_SCHEMA.FIELDS.PLATFORM] = PLATFORM.ANDROID;
android[Schema.APPLICATION_TABLE_SCHEMA.FIELDS.VERSION] = 1;
android[Schema.APPLICATION_TABLE_SCHEMA.FIELDS.IS_LATEST] = true;
android[Schema.APPLICATION_TABLE_SCHEMA.FIELDS.FORCE_UPDATE] = false;
return Promise.all([
// Inserts seed entries
knex(Schema.APPLICATION_TABLE_SCHEMA.TABLE_NAME).insert(ios),
knex(Schema.APPLICATION_TABLE_SCHEMA.TABLE_NAME).insert(android)
]);
});
};
/**
* Create health table for health-check
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const health = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return knex.schema.createTable(Schema.HEALTH_TABLE_SCHEMA.TABLE_NAME, (table => {
table.string(Schema.HEALTH_TABLE_SCHEMA.FIELDS.ID, 1).notNullable().primary();
}));
})
.then(() => {
return knex.raw(`INSERT INTO ${Schema.HEALTH_TABLE_SCHEMA.TABLE_NAME} VALUES ('1');`);
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return setting(knex, Promise);
})
.then(() => {
return role(knex, Promise);
})
.then(() => {
return user(knex, Promise);
})
.then(() => {
return sessions(knex, Promise);
})
.then(() => {
return devices(knex, Promise);
})
.then(() => {
return applications(knex, Promise);
})
.then(() => {
return health(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.SETTING_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.SESSION_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.USER_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.ROLE_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.DEVICE_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.APPLICATION_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.HEALTH_TABLE_SCHEMA.TABLE_NAME} CASCADE`)
]);
};
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
const user = (knex, Promise) => {
let SCHEMA = Schema.USER_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.table(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.PARENT_ID, 36).nullable().index()
.references(Schema.USER_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.USER_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.COMPANY, 255).nullable();
table.string(SCHEMA.FIELDS.ADDRESS, 255).nullable();
table.string(SCHEMA.FIELDS.COUNTRY, 255).nullable();
table.string(SCHEMA.FIELDS.STATE, 255).nullable();
table.string(SCHEMA.FIELDS.PROVINCE, 255).nullable();
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return user(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.table(`${Schema.USER_TABLE_SCHEMA.TABLE_NAME}`, function (table) {
table.dropColumn(`${Schema.USER_TABLE_SCHEMA.FIELDS.PARENT_ID}`);
table.dropColumn(`${Schema.USER_TABLE_SCHEMA.FIELDS.COMPANY}`);
table.dropColumn(`${Schema.USER_TABLE_SCHEMA.FIELDS.ADDRESS}`);
table.dropColumn(`${Schema.USER_TABLE_SCHEMA.FIELDS.COUNTRY}`);
table.dropColumn(`${Schema.USER_TABLE_SCHEMA.FIELDS.STATE}`);
table.dropColumn(`${Schema.USER_TABLE_SCHEMA.FIELDS.PROVINCE}`);
}),
]);
};
import { TAG_TABLE_SCHEMA, USER_TABLE_SCHEMA } from "./../schema";
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
/**
* Create tags table and its default data
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const tag = (knex, Promise) => {
let SCHEMA = Schema.TAG_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.USER_ID, 36).notNullable().index()
.references(Schema.USER_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.USER_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.NAME, 255).notNullable();
table.text(SCHEMA.FIELDS.DESCRIPTION).nullable();
});
});
};
const userTag = (knex, Promise) => {
let SCHEMA = Schema.USER_TAG_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.USER_ID, 36).notNullable().index()
.references(Schema.USER_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.USER_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.TAG_ID, 36).notNullable().index()
.references(Schema.TAG_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.TAG_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return tag(knex, Promise);
})
.then(() => {
return userTag(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.TAG_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME} CASCADE`)
]);
};
\ No newline at end of file
import { PACKAGE_TABLE_SCHEMA, USER_TABLE_SCHEMA } from "./../schema";
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
/**
* Create packages table
* @param Promise
* @return {Promise<any>}
*/
const packages = (knex, Promise) => {
let SCHEMA = Schema.PACKAGE_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.NAME, 255).notNullable();
table.text(SCHEMA.FIELDS.DESCRIPTION).nullable();
table.float(SCHEMA.FIELDS.NUMBER_ACCOUNT).defaultTo(0.0);
table.float(SCHEMA.FIELDS.NUMBER_FILE).defaultTo(0.0);
});
});
};
const userPackage = (knex, Promise) => {
let SCHEMA = Schema.USER_PACKAGE_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.USER_ID, 36).notNullable().index()
.references(Schema.USER_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.USER_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.PACKAGE_ID, 36).notNullable().index()
.references(Schema.PACKAGE_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.float(SCHEMA.FIELDS.NUMBER_ACCOUNT).defaultTo(0.0);
table.float(SCHEMA.FIELDS.NUMBER_FILE).defaultTo(0.0);
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return packages(knex, Promise);
})
.then(() => {
return userPackage(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.USER_PACKAGE_TABLE_SCHEMA.TABLE_NAME} CASCADE`)
]);
};
\ No newline at end of file
import { PRESENTATION_TABLE_SCHEMA, USER_TABLE_SCHEMA } from "./../schema";
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
/**
* Create presentation table
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const presentation = (knex, Promise) => {
let SCHEMA = Schema.PRESENTATION_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_ENABLE).notNullable().defaultTo(1);
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.USER_ID, 36).notNullable().index()
.references(Schema.USER_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.USER_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.TITLE, 255).notNullable();
table.string(SCHEMA.FIELDS.LANGUAGE, 255).notNullable();
table.text(SCHEMA.FIELDS.DESCRIPTION).nullable();
table.text(SCHEMA.FIELDS.IMAGE_URL).nullable();
table.text(SCHEMA.FIELDS.PAGE_TIMING).notNullable();
table.float(SCHEMA.FIELDS.NUMBER_PAGE).notNullable().defaultTo(0.0);
});
});
};
const accountPresentation = (knex, Promise) => {
let SCHEMA = Schema.USER_PRESENTATION_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.USER_ID, 36).notNullable().index()
.references(Schema.USER_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.USER_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.PRESENTATION_ID, 36).notNullable().index()
.references(Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return presentation(knex, Promise);
})
.then(() => {
return accountPresentation(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME} CASCADE`)
]);
};
\ No newline at end of file
import { PRESENTATION_TABLE_SCHEMA} from "./../schema";
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
/**
* Create presentation report table
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const presentationReport = (knex, Promise) => {
let SCHEMA = Schema.PRESENTATION_REPORT_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.USER_ID, 36).notNullable().index()
.references(Schema.USER_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.USER_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.PRESENTATION_ID, 36).notNullable().index()
.references(Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.text(SCHEMA.FIELDS.PAGE_TIMING).notNullable();
table.text(SCHEMA.FIELDS.NOTE).nullable();
table.text(SCHEMA.FIELDS.AUDIO_URL).notNullable();
table.double(SCHEMA.FIELDS.LATITUDE).notNullable().default(0);
table.double(SCHEMA.FIELDS.LONGITUDE).notNullable().default(0);
table.integer(SCHEMA.FIELDS.RATE).notNullable().default(0);
table.dateTime(SCHEMA.FIELDS.START_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.END_DATE).defaultTo(knex.raw("current_timestamp"));
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return presentationReport(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.PRESENTATION_REPORT_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
]);
};
\ No newline at end of file
import { USER_TABLE_SCHEMA } from "./../schema";
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
const userCode = (knex, Promise) => {
let SCHEMA = Schema.USER_CODE_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.USER_ID, 36).notNullable().index()
.references(Schema.USER_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.USER_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.CODE, 255).notNullable();
table.boolean(SCHEMA.FIELDS.IS_USED).notNullable().defaultTo(0);
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return userCode(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.USER_CODE_TABLE_SCHEMA.TABLE_NAME} CASCADE`)
]);
};
\ No newline at end of file
import { PACKAGE_TABLE_SCHEMA } from "./../schema";
import { PRIORITY } from "./../../../libs/scheduler";
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
const packages = (knex, Promise) => {
let SCHEMA = Schema.PACKAGE_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.table(SCHEMA.TABLE_NAME, (table) => {
table.integer(SCHEMA.FIELDS.PRIORITY, 11).notNullable().default(0);
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return packages(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.table(`${Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME}`, function (table) {
table.dropColumn(`${Schema.PACKAGE_TABLE_SCHEMA.FIELDS.PRIORITY}`);
}),
]);
};
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
const user = (knex, Promise) => {
let SCHEMA = Schema.USER_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.table(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.LANGUAGE, 255).nullable();
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return user(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.table(`${Schema.USER_TABLE_SCHEMA.TABLE_NAME}`, function (table) {
table.dropColumn(`${Schema.USER_TABLE_SCHEMA.FIELDS.LANGUAGE}`);
}),
]);
};
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
const packages = (knex, Promise) => {
let SCHEMA = Schema.PACKAGE_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.table(SCHEMA.TABLE_NAME, (table) => {
table.double(SCHEMA.FIELDS.PRICE).notNullable().default(0);
});
});
};
const userPackage = (knex, Promise) => {
let SCHEMA = Schema.USER_PACKAGE_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.table(SCHEMA.TABLE_NAME, (table) => {
table.double(SCHEMA.FIELDS.PRICE).notNullable().default(0);
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return packages(knex, Promise);
})
.then(() => {
return userPackage(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.table(`${Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME}`, function (table) {
table.dropColumn(`${Schema.PACKAGE_TABLE_SCHEMA.FIELDS.PRICE}`);
}),
knex.schema.table(`${Schema.USER_PACKAGE_TABLE_SCHEMA.TABLE_NAME}`, function (table) {
table.dropColumn(`${Schema.USER_PACKAGE_TABLE_SCHEMA.FIELDS.PRICE}`);
}),
]);
};
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
const presentation = (knex, Promise) => {
let SCHEMA = Schema.PRESENTATION_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.table(SCHEMA.TABLE_NAME, (table) => {
table.text(SCHEMA.FIELDS.FILE_URL).notNullable();
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return presentation(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.table(`${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}`, function (table) {
table.dropColumn(`${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.FILE_URL}`);
})
]);
};
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
const presentation = (knex, Promise) => {
let SCHEMA = Schema.PRESENTATION_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.table(SCHEMA.TABLE_NAME, (table) => {
table.integer(SCHEMA.FIELDS.PRIORITY).notNullable().default(0);
table.string(SCHEMA.FIELDS.USER_CODE, 255).nullable();
});
});
};
const userCode = (knex, Promise) => {
let SCHEMA = Schema.USER_CODE_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.table(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.NAME, 255).nullable();
});
});
};
const assignPresentation = (knex, Promise) => {
let SCHEMA = Schema.ASSIGN_PRESENTATION_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.PRESENTATION_ID, 36).notNullable().index()
.references(Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.ID)
.inTable(Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME)
.onUpdate("CASCADE")
.onDelete("CASCADE");
table.string(SCHEMA.FIELDS.COUNTRY, 255).nullable();
table.string(SCHEMA.FIELDS.STATE, 255).nullable();
table.string(SCHEMA.FIELDS.PROVINCE, 255).nullable();
table.text(SCHEMA.FIELDS.TAG).nullable();
table.text(SCHEMA.FIELDS.USER).nullable();
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return presentation(knex, Promise);
})
.then(() => {
return userCode(knex, Promise);
})
.then(() => {
return assignPresentation(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.table(`${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}`, function (table) {
table.dropColumn(`${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.PRIORITY}`);
table.dropColumn(`${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.USER_CODE}`);
}),
knex.schema.table(`${Schema.USER_CODE_TABLE_SCHEMA.TABLE_NAME}`, function (table) {
table.dropColumn(`${Schema.USER_CODE_TABLE_SCHEMA.FIELDS.NAME}`);
}),
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.ASSIGN_PRESENTATION_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
]);
};
\ No newline at end of file
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as Schema from "../schema";
import { LANGUAGE_TABLE_SCHEMA } from "./../schema";
/**
* Create tags table and its default data
* @param knex
* @param Promise
* @return {Promise<any>}
*/
const language = (knex, Promise) => {
let SCHEMA = LANGUAGE_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.string(SCHEMA.FIELDS.CODE, 36).notNullable();
table.string(SCHEMA.FIELDS.NAME, 36).notNullable();
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.integer(SCHEMA.FIELDS.PRIORITY, 6);
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return language(knex, Promise);
});
};
export const down = (knex: Knex, promise: typeof Bluebird): Bluebird<any> => {
return promise.resolve();
};
import * as Bluebird from "bluebird";
import * as Knex from "knex";
import * as UUID from "uuid";
import * as Schema from "../schema";
import { PLATFORM } from "../../../libs/constants";
/**
* Create media table and its default data
*
* @param knex
* @param Promise
* @returns {Promise<R>|Created|Promise<TResult>|PromiseLike<TResult>|Promise.<TResult>|Promise<R2|R1>}
*/
const media = (knex, Promise) => {
// create setting table;
let SCHEMA = Schema.MEDIA_TABLE_SCHEMA;
return Promise.resolve()
.then(() => {
return knex.schema.createTable(SCHEMA.TABLE_NAME, (table) => {
table.string(SCHEMA.FIELDS.ID, 36).notNullable().primary();
table.boolean(SCHEMA.FIELDS.IS_DELETED).notNullable().defaultTo(0);
table.boolean(SCHEMA.FIELDS.IS_ENABLE).notNullable().defaultTo(1);
table.dateTime(SCHEMA.FIELDS.CREATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.dateTime(SCHEMA.FIELDS.UPDATED_DATE).defaultTo(knex.raw("current_timestamp"));
table.text(SCHEMA.FIELDS.PATH).notNullable();
table.text(SCHEMA.FIELDS.URL).notNullable();
table.string(SCHEMA.FIELDS.HASH, 16).nullable();
});
});
};
export const up = (knex, Promise) => {
return Promise.resolve()
.then(() => {
return media(knex, Promise);
});
};
export const down = (knex, Promise) => {
return Promise.all([
knex.schema.raw(`DROP TABLE IF EXISTS ${Schema.MEDIA_TABLE_SCHEMA.TABLE_NAME} CASCADE`),
]);
};
\ No newline at end of file
import * as Bluebird from "bluebird";
import * as Knex from "knex";
export const up = (knex: Knex, promise: typeof Bluebird): Bluebird<any> => {
return promise.resolve();
};
export const down = (knex: Knex, promise: typeof Bluebird): Bluebird<any> => {
return promise.resolve();
};
\ No newline at end of file
import * as Bluebird from "bluebird";
import * as Knex from "knex";
export const up = (knex: Knex, promise: typeof Bluebird): Bluebird<any> => {
return promise.resolve();
};
export const down = (knex: Knex, promise: typeof Bluebird): Bluebird<any> => {
return promise.resolve();
};
\ No newline at end of file
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class ApplicationDto extends BaseDto<ApplicationDto> {
get tableName(): string {
return Schema.APPLICATION_TABLE_SCHEMA.TABLE_NAME;
}
}
export default ApplicationDto;
Database.bookshelf()["model"](Schema.APPLICATION_TABLE_SCHEMA.TABLE_NAME, ApplicationDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
// create by Nga
export class ArticlesDto extends BaseDto<ArticlesDto> {
get tableName(): string {
return Schema.ARTICLES_TABLE_SCHEMA.TABLE_NAME;
}
}
export default ArticlesDto;
Database.bookshelf()["model"](Schema.ARTICLES_TABLE_SCHEMA.TABLE_NAME, ArticlesDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class AssignPresentationDto extends BaseDto<AssignPresentationDto> {
get tableName(): string {
return Schema.ASSIGN_PRESENTATION_TABLE_SCHEMA.TABLE_NAME;
}
public presentation(): any {
return this.belongsTo(Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME, Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.PRESENTATION_ID);
}
}
export default AssignPresentationDto;
Database.bookshelf()["model"](Schema.ASSIGN_PRESENTATION_TABLE_SCHEMA.TABLE_NAME, AssignPresentationDto);
import * as UUID from "uuid";
import { Database } from "../connection";
export class BaseDto<T> extends Database.bookshelf().Model<any> {
public static knex() {
return Database.bookshelf().knex;
}
public static register(name: string, model: any): void {
Database.bookshelf()["model"](model);
}
private static generateUuid(model: any): void {
if (model.isNew()) {
model.set(model.idAttribute, UUID.v4());
}
}
constructor(attributes?: any, isNew?: boolean) {
super(attributes);
if (isNew != null) {
this.isNew = () => {
return isNew;
};
}
}
// noinspection JSMethodCanBeStatic
get idAttribute(): string {
return "id";
}
get isDelete(): string {
return "is_deleted";
}
get hasTimestamps(): string[] {
return ["created_date", "updated_date"];
}
public initialize(): void {
this.on("saving", BaseDto.generateUuid);
}
}
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
// create by Nga
export class CategoryDto extends BaseDto<CategoryDto> {
get tableName(): string {
return Schema.CATEGORY_TABLE_SCHEMA.TABLE_NAME;
}
}
export default CategoryDto;
Database.bookshelf()["model"](Schema.CATEGORY_TABLE_SCHEMA.TABLE_NAME, CategoryDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class DeviceDto extends BaseDto<DeviceDto> {
get tableName() {
return Schema.DEVICE_TABLE_SCHEMA.TABLE_NAME;
}
public user(): any {
return this.belongsTo(Schema.USER_TABLE_SCHEMA.TABLE_NAME, Schema.DEVICE_TABLE_SCHEMA.FIELDS.USER_ID);
}
}
export default DeviceDto;
// this fucking line of code just for bypass typescript compiler
Database.bookshelf()["model"](Schema.DEVICE_TABLE_SCHEMA.TABLE_NAME, DeviceDto);
export * from "./application.dto";
export * from "./assign_presentation.dto";
export * from "./base.dto";
export * from "./device.dto";
export * from "./language.dto";
export * from "./language.dto";
export * from "./media.dto";
export * from "./package.dto";
export * from "./presentation.dto";
export * from "./presentation_report.dto";
export * from "./role.dto";
export * from "./session.dto";
export * from "./setting.dto";
export * from "./tag.dto";
export * from "./user.dto";
export * from "./user_code.dto";
export * from "./user_package.dto";
export * from "./user_presentation.dto";
export * from "./user_tag.dto";
export * from "./category.dto";
export * from "./articles.dto";
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
// create by Nga
export class LanguageDto extends BaseDto<LanguageDto> {
get tableName(): string {
return Schema.LANGUAGE_TABLE_SCHEMA.TABLE_NAME;
}
}
export default LanguageDto;
Database.bookshelf()["model"](Schema.LANGUAGE_TABLE_SCHEMA.TABLE_NAME, LanguageDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class MediaDto extends BaseDto<MediaDto> {
get tableName(): string {
return Schema.MEDIA_TABLE_SCHEMA.TABLE_NAME;
}
}
export default MediaDto;
Database.bookshelf()["model"](Schema.MEDIA_TABLE_SCHEMA.TABLE_NAME, MediaDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class PackageDto extends BaseDto<PackageDto> {
get tableName(): string {
return Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME;
}
}
export default PackageDto;
Database.bookshelf()["model"](Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME, PackageDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class PresentationDto extends BaseDto<PresentationDto> {
get tableName(): string {
return Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME;
}
public user(): any {
return this.belongsTo(Schema.USER_TABLE_SCHEMA.TABLE_NAME, Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.USER_ID);
}
public assignPresentation(): any {
return this.belongsTo(Schema.ASSIGN_PRESENTATION_TABLE_SCHEMA.TABLE_NAME, Schema.ASSIGN_PRESENTATION_TABLE_SCHEMA.FIELDS.PRESENTATION_ID);
}
}
export default PresentationDto;
Database.bookshelf()["model"](Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME, PresentationDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class PresentationReportDto extends BaseDto<PresentationReportDto> {
get tableName(): string {
return Schema.PRESENTATION_REPORT_TABLE_SCHEMA.TABLE_NAME;
}
public user(): any {
return this.belongsTo(Schema.USER_TABLE_SCHEMA.TABLE_NAME, Schema.PRESENTATION_REPORT_TABLE_SCHEMA.FIELDS.USER_ID);
}
public presentation(): any {
return this.belongsTo(Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME, Schema.PRESENTATION_REPORT_TABLE_SCHEMA.FIELDS.PRESENTATION_ID);
}
}
export default PresentationReportDto;
Database.bookshelf()["model"](Schema.PRESENTATION_REPORT_TABLE_SCHEMA.TABLE_NAME, PresentationReportDto);
import { BaseDto } from "./base.dto";
import { ROLE_TABLE_SCHEMA } from "../schema";
import { Database } from "../connection";
export class RoleDto extends BaseDto<RoleDto> {
get tableName(): string {
return ROLE_TABLE_SCHEMA.TABLE_NAME;
}
}
export default RoleDto;
Database.bookshelf()["model"]("roles", RoleDto);
import { BaseDto } from "./base.dto";
import { SESSION_TABLE_SCHEMA , USER_TABLE_SCHEMA} from "./../schema";
import { Database } from "../connection";
export class SessionDto extends BaseDto<SessionDto> {
get tableName(): string {
return SESSION_TABLE_SCHEMA.TABLE_NAME;
}
public user(): any {
return this.belongsTo(USER_TABLE_SCHEMA.TABLE_NAME, SESSION_TABLE_SCHEMA.FIELDS.USER_ID);
}
}
export default SessionDto;
Database.bookshelf()["model"](SESSION_TABLE_SCHEMA.TABLE_NAME, SessionDto);
import { BaseDto } from "./base.dto";
import { SETTING_TABLE_SCHEMA } from "./../schema";
import { Database } from "../connection";
export class SettingDto extends BaseDto<SettingDto> {
get tableName(): string {
return SETTING_TABLE_SCHEMA.TABLE_NAME;
}
}
export default SettingDto;
Database.bookshelf()["model"](SETTING_TABLE_SCHEMA.TABLE_NAME, SettingDto);
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
import * as Schema from "../schema";
export class TagDto extends BaseDto<TagDto> {
get tableName(): string {
return Schema.TAG_TABLE_SCHEMA.TABLE_NAME;
}
public user(): any {
return this.belongsTo(Schema.USER_TABLE_SCHEMA.TABLE_NAME, Schema.TAG_TABLE_SCHEMA.FIELDS.USER_ID);
}
}
export default TagDto;
Database.bookshelf()["model"](Schema.TAG_TABLE_SCHEMA.TABLE_NAME, TagDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class UserDto extends BaseDto<UserDto> {
get tableName(): string {
return Schema.USER_TABLE_SCHEMA.TABLE_NAME;
}
public role(): any {
return this.belongsTo(Schema.ROLE_TABLE_SCHEMA.TABLE_NAME, Schema.USER_TABLE_SCHEMA.FIELDS.ROLE_ID);
}
public account(): any {
return this.hasMany(UserDto, Schema.USER_TABLE_SCHEMA.FIELDS.PARENT_ID).query(q => {
q.where(`${Schema.USER_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
});
}
public tag(): any {
return this.hasMany(Schema.TAG_TABLE_SCHEMA.TABLE_NAME, Schema.TAG_TABLE_SCHEMA.FIELDS.USER_ID).query(q => {
q.where(`${Schema.TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.TAG_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
});
}
public userTag(): any {
return this.hasMany(Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME).query(q => {
q.where(`${Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TAG_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
});
}
public userPackage(): any {
return this.hasMany(Schema.USER_PACKAGE_TABLE_SCHEMA.TABLE_NAME).query(q => {
q.where(`${Schema.USER_PACKAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PACKAGE_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
});
}
public presentation(): any {
return this.hasMany(Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME, Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.USER_ID).query(q => {
q.where(`${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
});
}
public userPresentation(): any {
return this.hasMany(Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME).query(q => {
q.where(`${Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
});
}
}
export default UserDto;
Database.bookshelf()["model"](Schema.USER_TABLE_SCHEMA.TABLE_NAME, UserDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class UserCodeDto extends BaseDto<UserCodeDto> {
get tableName(): string {
return Schema.USER_CODE_TABLE_SCHEMA.TABLE_NAME;
}
public user(): any {
return this.belongsTo(Schema.USER_TABLE_SCHEMA.TABLE_NAME, Schema.USER_CODE_TABLE_SCHEMA.FIELDS.USER_ID);
}
}
export default UserCodeDto;
Database.bookshelf()["model"](Schema.USER_CODE_TABLE_SCHEMA.TABLE_NAME, UserCodeDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class UserPackageDto extends BaseDto<UserPackageDto> {
get tableName(): string {
return Schema.USER_PACKAGE_TABLE_SCHEMA.TABLE_NAME;
}
public user(): any {
return this.belongsTo(Schema.USER_TABLE_SCHEMA.TABLE_NAME, Schema.USER_PACKAGE_TABLE_SCHEMA.FIELDS.USER_ID);
}
public package(): any {
return this.belongsTo(Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME, Schema.USER_PACKAGE_TABLE_SCHEMA.FIELDS.PACKAGE_ID);
}
}
export default UserPackageDto;
Database.bookshelf()["model"](Schema.USER_PACKAGE_TABLE_SCHEMA.TABLE_NAME, UserPackageDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class UserPresentationDto extends BaseDto<UserPresentationDto> {
get tableName(): string {
return Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME;
}
public user(): any {
return this.belongsTo(Schema.USER_TABLE_SCHEMA.TABLE_NAME, Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.USER_ID);
}
public presentation(): any {
return this.belongsTo(Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME, Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.PRESENTATION_ID);
}
}
export default UserPresentationDto;
Database.bookshelf()["model"](Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME, UserPresentationDto);
import * as Schema from "../schema";
import { BaseDto } from "./base.dto";
import { Database } from "../connection";
export class UserTagDto extends BaseDto<UserTagDto> {
get tableName(): string {
return Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME;
}
public user(): any {
return this.belongsTo(Schema.USER_TABLE_SCHEMA.TABLE_NAME, Schema.USER_TAG_TABLE_SCHEMA.FIELDS.USER_ID);
}
public tag(): any {
return this.belongsTo(Schema.TAG_TABLE_SCHEMA.TABLE_NAME, Schema.USER_TAG_TABLE_SCHEMA.FIELDS.TAG_ID);
}
}
export default UserTagDto;
Database.bookshelf()["model"](Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME, UserTagDto);
/**
* Created by phuongho on 15/08/17.
*/
export const HEALTH_TABLE_SCHEMA = {
TABLE_NAME: "health",
FIELDS: {
ID: "id"
}
};
export const APPLICATION_TABLE_SCHEMA = {
TABLE_NAME: "application",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
PLATFORM: "platform",
VERSION: "version",
IS_LATEST: "is_latest",
FORCE_UPDATE: "force_update"
}
};
export const SESSION_TABLE_SCHEMA = {
TABLE_NAME: "sessions",
FIELDS: {
ID: "id",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
IS_DELETED: "is_deleted",
USER_ID: "user_id",
TOKEN: "token",
EXPIRE: "expire",
HASH: "hash"
},
};
export const ROLE_TABLE_SCHEMA = {
TABLE_NAME: "roles",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
NAME: "name",
KEYWORD: "keyword",
DESCRIPTION: "description"
},
};
export const DEVICE_TABLE_SCHEMA = {
TABLE_NAME: "devices",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
USER_ID: "user_id",
DEVICE_ID: "device_id",
REGISTRAR_ID: "registrar_id",
DEVICE_OS: "device_os",
DEVICE_MODEL: "device_model",
DEVICE_NAME: "device_name",
OS_VERSION: "os_version",
APP_VERSION: "app_version",
BUILD_VERSION: "build_version",
IS_SANDBOX: "is_sandbox"
},
};
export const USER_TABLE_SCHEMA = {
TABLE_NAME: "users",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
IS_ENABLE: "is_enable",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
FIRST_NAME: "first_name",
LAST_NAME: "last_name",
PHONE_NUMBER: "phone_number",
EMAIL: "email",
PASSWORD: "password",
ROLE_ID: "role_id",
AVATAR_URL: "avatar_url",
PARENT_ID: "parent_id",
COMPANY: "company",
ADDRESS: "address",
COUNTRY: "country",
STATE: "state",
PROVINCE: "province",
TAG: "tag",
LANGUAGE: "language",
},
};
export const MEDIA_TABLE_SCHEMA = {
TABLE_NAME: "media",
FIELDS: {
ID: "id",
IS_ENABLE: "is_enable",
IS_DELETED: "is_deleted",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
PATH: "path",
URL: "url",
HASH: "hash",
},
};
export const TAG_TABLE_SCHEMA = {
TABLE_NAME: "tags",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
IS_ENABLE: "is_enable",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
USER_ID: "user_id",
NAME: "name",
DESCRIPTION: "description"
},
};
export const USER_TAG_TABLE_SCHEMA = {
TABLE_NAME: "user_tags",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
USER_ID: "user_id",
TAG_ID: "tag_id"
},
};
export const PACKAGE_TABLE_SCHEMA = {
TABLE_NAME: "packages",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
IS_ENABLE: "is_enable",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
NAME: "name",
DESCRIPTION: "description",
NUMBER_ACCOUNT: "number_account",
NUMBER_FILE: "number_file",
PRICE: "price",
PRIORITY: "priority"
},
};
export const USER_PACKAGE_TABLE_SCHEMA = {
TABLE_NAME: "user_packages",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
USER_ID: "user_id",
PACKAGE_ID: "package_id",
NUMBER_ACCOUNT: "number_account",
NUMBER_FILE: "number_file",
PRICE: "price"
},
};
export const PRESENTATION_TABLE_SCHEMA = {
TABLE_NAME: "presentation",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
IS_ENABLE: "is_enable",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
USER_ID: "user_id",
USER_CODE: "user_code",
TITLE: "title",
DESCRIPTION: "description",
IMAGE_URL: "image_url",
NUMBER_PAGE: "number_page",
PAGE_TIMING: "page_timing",
FILE_URL: "file_url",
LANGUAGE: "language",
PRIORITY: "priority"
},
};
export const ASSIGN_PRESENTATION_TABLE_SCHEMA = {
TABLE_NAME: "assign_presentation",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
PRESENTATION_ID: "presentation_id",
COUNTRY: "country",
STATE: "state",
PROVINCE: "province",
TAG: "tags",
USER: "users"
},
};
export const USER_PRESENTATION_TABLE_SCHEMA = {
TABLE_NAME: "user_presentation",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
USER_ID: "user_id",
PRESENTATION_ID: "presentation_id"
},
};
export const PRESENTATION_REPORT_TABLE_SCHEMA = {
TABLE_NAME: "presentation_report",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
USER_ID: "user_id",
PRESENTATION_ID: "presentation_id",
START_DATE: "start_date",
END_DATE: "end_date",
PAGE_TIMING: "page_timing",
LATITUDE: "latitude",
LONGITUDE: "longitude",
NOTE: "note",
AUDIO_URL: "audio_url",
RATE: "rate",
}
};
export const USER_CODE_TABLE_SCHEMA = {
TABLE_NAME: "user_codes",
FIELDS: {
ID: "id",
IS_DELETED: "is_deleted",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
USER_ID: "user_id",
NAME: "name",
CODE: "code",
IS_USED: "is_used"
},
};
export const SETTING_TABLE_SCHEMA = {
TABLE_NAME: "settings",
FIELDS: {
ID: "id",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
IS_ENABLE: "is_enable",
IS_DELETED: "is_deleted",
KEYWORD: "key",
VALUE: "value",
DESC: "description",
},
};
export const LANGUAGE_TABLE_SCHEMA = {
TABLE_NAME: "languages",
FIELDS: {
ID: "id",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
IS_DELETED: "is_deleted",
NAME: "name",
CODE: "code",
PRIORITY: "priority",
},
};
// create by Anh Nga 31-10-2017
export const CATEGORY_TABLE_SCHEMA = {
TABLE_NAME: "category",
FIELDS: {
ID: "id",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
IS_DELETED: "is_deleted",
NAME: "name",
},
};
export const ARTICLES_TABLE_SCHEMA = {
TABLE_NAME: "articles",
FIELDS: {
ID: "id",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
IS_DELETED: "is_deleted",
TITLE: "title",
CATEGORY_ID: "category_id",
},
};
export const COMMENT_TABLE_SCHEMA = {
TABLE_NAME: "comment",
FIELDS: {
ID: "id",
CREATED_DATE: "created_date",
UPDATED_DATE: "updated_date",
IS_DELETED: "is_deleted",
NAME_FB: "name_fb",
ARTICLES_ID: "articles_id",
DETAIL_COMMENT: "detail_comment",
},
};
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, TagModel } from "./../models";
import { TAG_TABLE_SCHEMA } from "./sql/schema";
import { TagDto } from "./sql/models";
import { injectable, inject } from "inversify";
@injectable()
export class TagRepository extends BaseRepository<TagDto, TagModel> {
constructor( @inject("Logger") log?: Log) {
super(TagDto, TagModel, log);
}
/**
* search Tag
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<TagModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.where(`${Schema.TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.TAG_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.TAG_TABLE_SCHEMA.FIELDS.NAME}`, "ILIKE", `%${keyword}%`);
});
}
if (searchParams.userId) {
q.where(`${Schema.TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.TAG_TABLE_SCHEMA.FIELDS.USER_ID}`, searchParams.userId);
}
let orderBy = searchParams.orderBy || `${Schema.TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.TAG_TABLE_SCHEMA.FIELDS.CREATED_DATE}`;
let orderType = searchParams.orderType || "DESC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default TagRepository;
import { BaseRepository, Log } from "./base.repository";
import { UserDto } from "./sql/models";
import { UserModel, CollectionWrap } from "../models";
import * as Schema from "../data/sql/schema";
import * as Promise from "bluebird";
import { DELETE_STATUS, ROLE } from "../libs/constants";
import { injectable, inject } from "inversify";
@injectable()
export class UserRepository extends BaseRepository<UserDto, UserModel> {
constructor( @inject("Logger") log?: Log) {
super(UserDto, UserModel, log);
}
/**
*
* @param email
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public findByEmail(email: string, related = [], filters = []): Promise<UserModel> {
return this.findOneByQuery(q => {
q.where(Schema.USER_TABLE_SCHEMA.FIELDS.EMAIL, email);
q.where(Schema.USER_TABLE_SCHEMA.FIELDS.IS_DELETED, DELETE_STATUS.NO);
}, related, filters);
}
/**
* search User
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<UserModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.where(`${Schema.USER_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.tags) {
let tags = searchParams.tags.split(",");
q.leftJoin(`${Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME}`, `${Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TAG_TABLE_SCHEMA.FIELDS.USER_ID}`, `${Schema.USER_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TABLE_SCHEMA.FIELDS.ID}`);
q.whereIn(Schema.USER_TAG_TABLE_SCHEMA.FIELDS.TAG_ID, tags);
}
if (searchParams.parentId) {
q.where(`${Schema.USER_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TABLE_SCHEMA.FIELDS.PARENT_ID}`, searchParams.parentId);
}
if (searchParams.currentUserId) {
q.where(`${Schema.USER_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TABLE_SCHEMA.FIELDS.ID}`, "!=", searchParams.currentUserId);
}
if (searchParams.roleId) {
q.where(Schema.USER_TABLE_SCHEMA.FIELDS.ROLE_ID, searchParams.roleId);
}
if (searchParams.country) {
q.where(Schema.USER_TABLE_SCHEMA.FIELDS.COUNTRY, "ILIKE", searchParams.country);
}
if (searchParams.state) {
q.where(Schema.USER_TABLE_SCHEMA.FIELDS.STATE, "ILIKE", searchParams.state);
}
if (searchParams.province) {
q.where(Schema.USER_TABLE_SCHEMA.FIELDS.PROVINCE, "ILIKE", searchParams.province);
}
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.USER_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TABLE_SCHEMA.FIELDS.FIRST_NAME}`, "ILIKE", `%${keyword}%`);
q1.where(`${Schema.USER_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TABLE_SCHEMA.FIELDS.LAST_NAME}`, "ILIKE", `%${keyword}%`);
q1.orWhere(`${Schema.USER_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TABLE_SCHEMA.FIELDS.EMAIL}`, "ILIKE", `%${keyword}%`);
});
}
let orderBy = searchParams.orderBy || `${Schema.USER_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TABLE_SCHEMA.FIELDS.FIRST_NAME}`;
let orderType = searchParams.orderType || "ASC";
q.orderByRaw(`lower(${orderBy}) ${orderType}`);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default UserRepository;
import { Log } from "./../libs/logger";
import { USER_CODE_TABLE_SCHEMA } from "./sql/schema";
import { CollectionWrap } from "./../models/collections";
import { BaseRepository } from "./base.repository";
import { UserCodeDto } from "./sql/models";
import { UserCodeModel } from "../models";
import * as Schema from "../data/sql/schema";
import * as Promise from "bluebird";
import { injectable, inject } from "inversify";
@injectable()
export class UserCodeRepository extends BaseRepository<UserCodeDto, UserCodeModel> {
constructor( @inject("Logger") log?: Log) {
super(UserCodeDto, UserCodeModel, log);
}
/**
* search UserCode
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<UserCodeModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.where(`${Schema.USER_CODE_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_CODE_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.USER_CODE_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_CODE_TABLE_SCHEMA.FIELDS.NAME}`, "ILIKE", `%${keyword}%`);
});
}
if (searchParams.userId) {
q.where(`${Schema.USER_CODE_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_CODE_TABLE_SCHEMA.FIELDS.USER_ID}`, searchParams.userId);
}
if (searchParams.isUsed) {
q.where(`${Schema.USER_CODE_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_CODE_TABLE_SCHEMA.FIELDS.IS_USED}`, searchParams.isUsed);
}
let orderBy = searchParams.orderBy || `${Schema.USER_CODE_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_CODE_TABLE_SCHEMA.FIELDS.CREATED_DATE}`;
let orderType = searchParams.orderType || "DESC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
/**
*
* @param code
* @param related
* @param filters
*/
public findByCode(code: string, related = [], filters = []): Promise<UserCodeModel> {
let conditions: any = {};
conditions[Schema.USER_CODE_TABLE_SCHEMA.FIELDS.CODE] = code;
conditions[Schema.USER_CODE_TABLE_SCHEMA.FIELDS.IS_DELETED] = false;
conditions[Schema.USER_CODE_TABLE_SCHEMA.FIELDS.IS_USED] = false;
return this.findOneByAtribute({ conditions: conditions });
}
}
export default UserCodeRepository;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, UserPackageModel } from "./../models";
import { USER_PACKAGE_TABLE_SCHEMA } from "./sql/schema";
import { UserPackageDto } from "./sql/models";
import { injectable, inject } from "inversify";
@injectable()
export class UserPackageRepository extends BaseRepository<UserPackageDto, UserPackageModel> {
constructor( @inject("Logger") log?: Log) {
super(UserPackageDto, UserPackageModel, log);
}
/**
* search UserPackage
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<UserPackageModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.leftJoin(`${Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME}`, `${Schema.USER_PACKAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PACKAGE_TABLE_SCHEMA.FIELDS.PACKAGE_ID}`, `${Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.PACKAGE_TABLE_SCHEMA.FIELDS.ID}`);
q.where(`${Schema.USER_PACKAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PACKAGE_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.PACKAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.PACKAGE_TABLE_SCHEMA.FIELDS.NAME}`, "ILIKE", `%${keyword}%`);
});
}
if (searchParams.userId) {
q.where(`${Schema.USER_PACKAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PACKAGE_TABLE_SCHEMA.FIELDS.USER_ID}`, searchParams.userId);
}
let orderBy = searchParams.orderBy || `${Schema.USER_PACKAGE_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PACKAGE_TABLE_SCHEMA.FIELDS.CREATED_DATE}`;
let orderType = searchParams.orderType || "DESC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
/**
*
* @param userId
*/
public getInfoByUserId(userId: string): Promise<{ numberFile: number, numberAccount: number }> {
let ret: any = null;
let numberFile: number = 0;
let numberAccount: number = 0;
return this.findByQuery(q => {
q.where(Schema.USER_PACKAGE_TABLE_SCHEMA.FIELDS.IS_DELETED, false);
q.where(Schema.USER_PACKAGE_TABLE_SCHEMA.FIELDS.USER_ID, userId);
})
.then(objects => {
if (objects) {
objects.forEach(item => {
numberFile += item.numberFile;
numberAccount += item.numberAccount;
});
ret = {};
ret.numberFile = numberFile;
ret.numberAccount = numberAccount;
}
return ret;
});
}
}
export default UserPackageRepository;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, UserPresentationModel } from "./../models";
import { USER_PRESENTATION_TABLE_SCHEMA } from "./sql/schema";
import { UserPresentationDto } from "./sql/models";
import { injectable, inject } from "inversify";
@injectable()
export class UserPresentationRepository extends BaseRepository<UserPresentationDto, UserPresentationModel> {
constructor( @inject("Logger") log?: Log) {
super(UserPresentationDto, UserPresentationModel, log);
}
/**
* search UserPresentation
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<UserPresentationModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.leftJoin(`${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}`, `${Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.PRESENTATION_ID}`, `${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.ID}`);
q.where(`${Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.TITLE}`, "ILIKE", `%${keyword}%`);
});
}
if (searchParams.userId) {
q.where(`${Schema.USER_PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.USER_ID}`, searchParams.userId);
}
let orderBy = searchParams.orderBy || `${Schema.PRESENTATION_TABLE_SCHEMA.TABLE_NAME}.${Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.PRIORITY}`;
let orderType = searchParams.orderType || "ASC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default UserPresentationRepository;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseRepository, Log } from "./base.repository";
import { CollectionWrap, UserTagModel } from "./../models";
import { USER_TAG_TABLE_SCHEMA } from "./sql/schema";
import { UserTagDto } from "./sql/models";
import { injectable, inject } from "inversify";
@injectable()
export class UserTagRepository extends BaseRepository<UserTagDto, UserTagModel> {
constructor( @inject("Logger") log?: Log) {
super(UserTagDto, UserTagModel, log);
}
/**
* search UserTag
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {Promise<any[]>}
*/
public search(searchParams: any = {}, offset: number, limit: number, related = [], filters = []): Promise<CollectionWrap<UserTagModel>> {
let keyword = searchParams.key || null;
limit = limit || null;
offset = offset || null;
let query = () => {
return (q): void => {
q.leftJoin(`${Schema.TAG_TABLE_SCHEMA.TABLE_NAME}`, `${Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TAG_TABLE_SCHEMA.FIELDS.TAG_ID}`, `${Schema.TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.TAG_TABLE_SCHEMA.FIELDS.ID}`);
q.where(`${Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TAG_TABLE_SCHEMA.FIELDS.IS_DELETED}`, false);
if (searchParams.key) {
q.where(q1 => {
q1.where(`${Schema.TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.TAG_TABLE_SCHEMA.FIELDS.NAME}`, "ILIKE", `%${keyword}%`);
});
}
if (searchParams.userId) {
q.where(`${Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TAG_TABLE_SCHEMA.FIELDS.USER_ID}`, searchParams.userId);
}
let orderBy = searchParams.orderBy || `${Schema.USER_TAG_TABLE_SCHEMA.TABLE_NAME}.${Schema.USER_TAG_TABLE_SCHEMA.FIELDS.CREATED_DATE}`;
let orderType = searchParams.orderType || "DESC";
q.orderBy(orderBy, orderType);
};
};
return this.queryByPage(query(), offset, limit, related, filters);
}
}
export default UserTagRepository;
/**
* Created by Anh Nga on 13/10/2017
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, ArticlesModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ErrorCode, HttpStatus, logger as Logger } from "../libs";
import { ArticlesRepository } from "../data";
import { injectable, inject } from "inversify";
@injectable()
export class ArticlesService extends BaseService<ArticlesModel, ArticlesRepository> {
constructor(repo: ArticlesRepository, @inject("Logger") logger?: Log) {
super(repo, logger);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<ArticlesModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param data
* @param related
* @param filters
*/
public create(data: ArticlesModel, related = [], filters = []): Promise<ArticlesModel> {
let conditions: any = {};
conditions[Schema.ARTICLES_TABLE_SCHEMA.FIELDS.TITLE] = data.name;
return this.repo.findOneByAtribute({ conditions: conditions })
.then(object => {
if (object != null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.CODE,
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return this.insert(data);
});
}
}
export default ArticlesService;
/**
* Created by phuongho on 05/10/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, AssignPresentationModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ErrorCode, HttpStatus, Logger } from "../libs";
import { PresentationRepository, UserPresentationRepository, AssignPresentationRepository } from "./../data";
import { UserPresentationModel } from "./../models";
import { injectable, inject } from "inversify";
@injectable()
export class AssignPresentationService extends BaseService<AssignPresentationModel, AssignPresentationRepository> {
constructor(private userPresent: UserPresentationRepository,
private present: PresentationRepository,
repo: AssignPresentationRepository,
@inject("Logger") logger?: Log) {
super(repo, logger);
}
/**
* Invoke default repository
* @param data
* @param related
* @param filters
*/
public create<T>(data: AssignPresentationModel, related: string[] = [], filters: string[] = []): Promise<AssignPresentationModel> {
return this.present.findById(data.presentationId)
.then(object => {
if (object === null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.NOT_FOUND.CODE,
ErrorCode.RESOURCE.NOT_FOUND.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return this.repo.deleteByQuery(q => {
q.where(Schema.ASSIGN_PRESENTATION_TABLE_SCHEMA.FIELDS.PRESENTATION_ID, data.presentationId);
});
})
.then(() => {
return this.insert(data);
})
.tap(() => {
return this.userPresent.deleteByQuery(q => {
q.where(Schema.USER_PRESENTATION_TABLE_SCHEMA.FIELDS.PRESENTATION_ID, data.presentationId);
});
})
.tap((object) => {
if (data.users) {
data.users.forEach(userId => {
let model = new UserPresentationModel();
model.userId = userId;
model.presentationId = data.presentationId;
this.userPresent.insert(model);
});
}
});
}
/**
*
* @param presentationId
* @param related
* @param filters
*/
public detailByPresentaionId(presentationId: string, related: string[] = [], filters: string[] = []): Promise<AssignPresentationModel> {
return this.repo.findOneByQuery(q => {
q.where(Schema.ASSIGN_PRESENTATION_TABLE_SCHEMA.FIELDS.PRESENTATION_ID, presentationId);
}, related, filters);
}
}
export default AssignPresentationService;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as _ from "lodash";
import { BaseModel, CollectionWrap, ExceptionModel } from "../models";
import { BaseRepository } from "../data";
import { ErrorCode, HttpStatus } from "../libs";
import { QueryBuilder } from "knex";
import { WithRelatedQuery } from "bookshelf";
import { injectable, unmanaged } from "inversify";
export interface Log {
error(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
info(message: string, meta?: any): void;
debug(message: string, meta?: any): void;
}
@injectable()
export class BaseService<M extends BaseModel, R extends BaseRepository<any, M>> {
constructor( @unmanaged() protected repo?: R, @unmanaged() protected logger?: Log) {
this.logger = logger || {
error: (message: string, meta?: any): void => { },
warn: (message: string, meta?: any): void => { },
info: (message: string, meta?: any): void => { },
debug: (message: string, meta?: any): void => { },
};
this.repo = repo || {} as R;
}
/**
*
* @param model
* @param related
* @param filters
*/
public update(model: M, related = [], filters = []): Promise<any> {
return this.detailById(model.id)
.then(object => {
if (!object || object.isDeleted) {
throw new ExceptionModel(
ErrorCode.RESOURCE.NOT_FOUND.CODE,
ErrorCode.RESOURCE.NOT_FOUND.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
);
}
return this.repo.update(model);
});
}
/**
*
* @param model
*/
public insert(model: M): Promise<any> {
return this.repo.insert(model);
}
/**
* @param model
* @param related
* @param filters
*/
public insertGet(model: M, related: string[] = [], filters: string[] = []): Promise<M> {
return this.repo.insertGet(model, related, filters);
}
/**
* @param id
*/
public forceDelete(id: string): Promise<boolean> {
return this.repo.forceDelete(id);
}
/**
*
* @param id
*/
public deleteLogic(id: string): Promise<M> {
return this.repo.deleteLogic(id);
}
/**
* @param id
*/
public removeById(id: string): Promise<any> {
return this.detailById(id)
.then((object) => {
return this.deleteLogic(object.id);
})
.then(object => {
if (object) {
return true;
}
return false;
});
}
/**
* @param id
* @param related
* @param filters
*/
public detailById(id: string, related = [], filters = []): Promise<M> {
return this.findById(id, related, filters)
.then(object => {
if (object === null || object.isDeleted === true) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.NOT_FOUND.CODE,
ErrorCode.RESOURCE.NOT_FOUND.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return object;
});
}
/**
*
* @param id
* @param related
* @param filters
*/
public findOne(id: string, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Promise<M> {
return this.findById(id, related, filters);
}
/**
*
* @param id
* @param related
* @param filters
*/
public findById(id: string, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Promise<M> {
return this.repo.findById(id, related, filters);
}
/**
*
* @param model
* @param related
* @param filters
*/
public make(model: M, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Promise<M> {
return Promise.resolve()
.then(() => {
return this.repo.insert(model);
})
.then((object) => {
return this.findOne(object.id, [], filters);
});
}
/**
*
* @param id
* @param related
* @param filters
*/
public delete(id: string, related: (string | WithRelatedQuery)[] = [], filters: string[] = []): Promise<string> {
return this.repo.deleteLogic(id)
.then(() => {
return id;
});
}
}
export default BaseService;
import Redis from "../data/redis/redis";
import { BaseService, Log } from "./base.service";
import { injectable, inject } from "inversify";
@injectable()
export class CacheService extends BaseService<any, any> {
constructor(@inject("Logger") log?: Log) {
super(null, log);
}
/**
* Create a unique key in redis
* @param params array of string
*/
private createKey(...params: string[]): string {
return params.filter(val => val != null && val !== "").join(":");
}
public get(key: string): any {
return Redis.getClient().getAsync(key);
}
public set(key: string, val: any, expire?: number): any {
if (expire != null) {
return Redis.getClient().setAsync(key, val, "EX", expire);
}
return Redis.getClient().setAsync(key, val);
}
}
export default CacheService;
/**
* Created by Anh Nga on 13/10/2017
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, CategoryModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ErrorCode, HttpStatus, logger as Logger } from "../libs";
import { CategoryRepository } from "../data";
import { injectable, inject } from "inversify";
@injectable()
export class CategoryService extends BaseService<CategoryModel, CategoryRepository> {
constructor(repo: CategoryRepository, @inject("Logger") logger?: Log) {
super(repo, logger);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<CategoryModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param data
* @param related
* @param filters
*/
public create(data: CategoryModel, related = [], filters = []): Promise<CategoryModel> {
let conditions: any = {};
conditions[Schema.CATEGORY_TABLE_SCHEMA.FIELDS.NAME] = data.name;
return this.repo.findOneByAtribute({ conditions: conditions })
.then(object => {
if (object != null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.CODE,
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return this.insert(data);
});
}
}
export default CategoryService;
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { DeviceModel } from "../models";
import { DeviceRepository } from "../data";
import { injectable, inject } from "inversify";
/**
* Created by phuongho on 15/08/17.
*/
@injectable()
export class DeviceService extends BaseService<DeviceModel, DeviceRepository> {
constructor(repo: DeviceRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
/**
*
* @param model
* @param related
* @param filters
* @returns {any}
*/
public create(model: DeviceModel, related = [], filters = []): Promise<DeviceModel> {
if (model != null) {
return this.repo.findByDeviceId(model.deviceId)
.then(device => {
if (device != null) {
model.id = device.id;
return this.repo.update(model);
} else {
return this.repo.insert(model);
}
})
.then((object) => {
return this.repo.findOne(object.id, related, filters);
});
}
return Promise.resolve(null);
}
/**
*
* @param userId
* @param deviceId
* @param ignoreDevices
* @returns {any}
*/
public deleteByUserId(userId: string, deviceId?: string, ignoreDevices?: string[]): Promise<any> {
if (userId != null) {
return this.repo.deleteByQuery(q => {
q.where(Schema.DEVICE_TABLE_SCHEMA.FIELDS.USER_ID, userId);
if (deviceId != null) {
q.where(Schema.DEVICE_TABLE_SCHEMA.FIELDS.DEVICE_ID, deviceId);
}
if (ignoreDevices != null && ignoreDevices.length > 0) {
q.whereNotIn(Schema.DEVICE_TABLE_SCHEMA.FIELDS.DEVICE_ID, ignoreDevices);
}
});
}
return Promise.resolve(null);
}
/**
* Get devices by user id.
* @returns {Promise<any>}
* @param userId
*/
public getDeviceByUserId(userId: string): Promise<DeviceModel> {
return this.repo.findOneByQuery(q => {
q.where(Schema.DEVICE_TABLE_SCHEMA.FIELDS.USER_ID, userId);
}, ["user"]);
}
}
export default DeviceService;
import { platform } from "os";
import * as Bluebird from "bluebird";
import { injectable, inject } from "inversify";
import { BaseService, Log } from "./base.service";
import { ApplicationRepository } from "../data";
import { ApplicationModel, CollectionWrap } from "../models";
import { QueryBuilder } from "knex";
import * as Schema from "../data/sql/schema";
@injectable()
export class DevOpsService extends BaseService<ApplicationModel, ApplicationRepository> {
constructor(repo: ApplicationRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
public listAppVersion(params: any, offset?: number, limit?: number, related = [], filters = []): Bluebird<CollectionWrap<ApplicationModel>> {
let query = () => {
return (q: QueryBuilder): void => {
if (params.platform) {
q.where(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.PLATFORM, params.platform);
}
if (params.version) {
q.where(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.VERSION, params.version);
}
q.orderBy(`${Schema.APPLICATION_TABLE_SCHEMA.FIELDS.VERSION}`, "DESC");
};
};
return this.repo.queryByPage(query(), offset, limit, ["isDeleted", "isEnable", "createdDate", "updatedDate"]);
}
public findAppVersion(platform: string, version: number): Bluebird<ApplicationModel> {
return this.repo.findOneByQuery(q => {
q.where(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.PLATFORM, platform);
q.where(Schema.APPLICATION_TABLE_SCHEMA.FIELDS.VERSION, version);
});
}
}
import { ArticlesService } from "./articles.service";
import { CategoryService } from "./category.service";
/**
* Created by phuongho on 15/08/17.
*/
import { AssignPresentationService } from "./assign_presentation.service";
import { CacheService } from "./cache.service";
import { DeviceService } from "./device.service";
import { DevOpsService } from "./devops.service";
import { LanguageService } from "./language.service";
import { MediaService } from "./media.service";
import { NotificationService } from "./notification.service";
import { PackageService } from "./package.service";
import { PresentationService } from "./presentation.service";
import { RoleService } from "./role.service";
import { SessionService } from "./session.service";
import { SettingService } from "./setting.service";
import { TagService } from "./tag.service";
import { UserCodeService } from "./user_code.service";
import { UserPackageService } from "./user_package.service";
import { UserPresentationService } from "./user_presentation.service";
import { UserService } from "./user.service";
import { UserTagService } from "./user_tag.service";
import {
ApplicationRepository,
AssignPresentationRepository,
DeviceRepository,
LanguageRepository,
MediaRepository,
PackageRepository,
PresentationRepository,
RoleRepository,
SessionRepository,
SettingRepository,
TagRepository,
UserCodeRepository,
UserPackageRepository,
UserPresentationRepository,
UserRepository,
UserTagRepository,
CategoryRepository,
ArticlesRepository,
} from "../data";
import { FCMPush, FirebaseAdmin, JsonWebToken, Logger, Mailer } from "../libs";
import { fcm, firebase, jwt, logger, mailer } from "../libs";
import { Container } from "inversify";
export const IoC = new Container();
// register static libraries
IoC.bind<FCMPush>(FCMPush).toConstantValue(fcm);
IoC.bind<FirebaseAdmin>(FirebaseAdmin).toConstantValue(firebase);
IoC.bind<JsonWebToken>(JsonWebToken).toConstantValue(jwt);
IoC.bind<Logger>(Logger).toConstantValue(logger);
IoC.bind<Logger>("Logger").toConstantValue(logger);
IoC.bind<Mailer>(Mailer).toConstantValue(mailer);
// register repositories
IoC.bind<ApplicationRepository>(ApplicationRepository).toSelf();
IoC.bind<AssignPresentationRepository>(AssignPresentationRepository).toSelf();
IoC.bind<DeviceRepository>(DeviceRepository).toSelf();
IoC.bind<LanguageRepository>(LanguageRepository).toSelf();
IoC.bind<MediaRepository>(MediaRepository).toSelf();
IoC.bind<PackageRepository>(PackageRepository).toSelf();
IoC.bind<PresentationRepository>(PresentationRepository).toSelf();
IoC.bind<RoleRepository>(RoleRepository).toSelf();
IoC.bind<SessionRepository>(SessionRepository).toSelf();
IoC.bind<SettingRepository>(SettingRepository).toSelf();
IoC.bind<TagRepository>(TagRepository).toSelf();
IoC.bind<UserCodeRepository>(UserCodeRepository).toSelf();
IoC.bind<UserPackageRepository>(UserPackageRepository).toSelf();
IoC.bind<UserPresentationRepository>(UserPresentationRepository).toSelf();
IoC.bind<UserRepository>(UserRepository).toSelf();
IoC.bind<UserTagRepository>(UserTagRepository).toSelf();
IoC.bind<CategoryRepository>(CategoryRepository).toSelf();
IoC.bind<ArticlesRepository>(ArticlesRepository).toSelf();
// register services
IoC.bind<AssignPresentationService>(AssignPresentationService).toSelf();
IoC.bind<CacheService>(CacheService).toSelf();
IoC.bind<DeviceService>(DeviceService).toSelf();
IoC.bind<DevOpsService>(DevOpsService).toSelf();
IoC.bind<LanguageService>(LanguageService).toSelf();
IoC.bind<MediaService>(MediaService).toSelf();
IoC.bind<NotificationService>(NotificationService).toSelf();
IoC.bind<PackageService>(PackageService).toSelf();
IoC.bind<PresentationService>(PresentationService).toSelf();
IoC.bind<RoleService>(RoleService).toSelf();
IoC.bind<SessionService>(SessionService).toSelf();
IoC.bind<SettingService>(SettingService).toSelf();
IoC.bind<TagService>(TagService).toSelf();
IoC.bind<UserCodeService>(UserCodeService).toSelf();
IoC.bind<UserPackageService>(UserPackageService).toSelf();
IoC.bind<UserPresentationService>(UserPresentationService).toSelf();
IoC.bind<UserService>(UserService).toSelf();
IoC.bind<UserTagService>(UserTagService).toSelf();
IoC.bind<CategoryService>(CategoryService).toSelf();
IoC.bind<ArticlesService>(ArticlesService).toSelf();
export default IoC;
// Will be remove when support upper layer
export const assignPresentationService = IoC.get<AssignPresentationService>(AssignPresentationService);
export const cacheService = IoC.get<CacheService>(CacheService);
export const deviceService = IoC.get<DeviceService>(DeviceService);
export const devOpsService = IoC.get<DevOpsService>(DevOpsService);
export const languageService = IoC.get<LanguageService>(LanguageService);
export const mediaService = IoC.get<MediaService>(MediaService);
export const notificationService = IoC.get<NotificationService>(NotificationService);
export const packageService = IoC.get<PackageService>(PackageService);
export const presentationService = IoC.get<PresentationService>(PresentationService);
export const roleService = IoC.get<RoleService>(RoleService);
export const sessionService = IoC.get<SessionService>(SessionService);
export const settingService = IoC.get<SettingService>(SettingService);
export const tagService = IoC.get<TagService>(TagService);
export const userCodeService = IoC.get<UserCodeService>(UserCodeService);
export const userPackageService = IoC.get<UserPackageService>(UserPackageService);
export const userPresentationService = IoC.get<UserPresentationService>(UserPresentationService);
export const userService = IoC.get<UserService>(UserService);
export const userTagService = IoC.get<UserTagService>(UserTagService);
export const categoryService = IoC.get<CategoryService>(CategoryService);
export const articlesService = IoC.get<ArticlesService>(ArticlesService);
/**
* Created by Anh Nga on 13/10/2017
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, LanguageModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ErrorCode, HttpStatus, logger as Logger } from "../libs";
import { LanguageRepository } from "../data";
import { injectable, inject } from "inversify";
@injectable()
export class LanguageService extends BaseService<LanguageModel, LanguageRepository> {
constructor(repo: LanguageRepository, @inject("Logger") logger?: Log) {
super(repo, logger);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<LanguageModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param data
* @param related
* @param filters
*/
public create(data: LanguageModel, related = [], filters = []): Promise<LanguageModel> {
let conditions: any = {};
conditions[Schema.LANGUAGE_TABLE_SCHEMA.FIELDS.NAME] = data.name;
return this.repo.findOneByAtribute({ conditions: conditions })
.then(object => {
if (object != null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.CODE,
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return this.insert(data);
});
}
}
export default LanguageService;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, MediaModel } from "../models";
import { MediaRepository } from "../data";
import { injectable, inject } from "inversify";
@injectable()
export class MediaService extends BaseService<MediaModel, MediaRepository> {
constructor(repo: MediaRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
findByHash(hash: string): Promise<CollectionWrap<MediaModel>> {
let ret = new CollectionWrap<MediaModel>();
if (hash == null || hash === "") {
Promise.resolve(ret);
}
return Promise.resolve()
.then(() => {
return this.repo.findByQuery(q => {
q.where(Schema.MEDIA_TABLE_SCHEMA.FIELDS.HASH, hash);
});
})
.then((objects) => {
ret.total = objects.length;
ret.data = objects;
return ret;
});
}
}
export default MediaService;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as stringFormat from "string-format";
import { BaseService, Log } from "./base.service";
import { DEVICE_OS } from "../libs/constants";
import { DeviceRepository } from "../data";
import { FCMPush } from "../libs/fcm";
import { NotificationModel, DeviceModel, UserModel } from "../models";
import { Utils } from "../libs";
import { injectable, inject } from "inversify";
@injectable()
export class NotificationService extends BaseService<any, any> {
constructor(private device: DeviceRepository, private fcm: FCMPush, @inject("Logger") log?: Log) {
super(null, log);
}
/**
*
* @param message
* @returns {Promise<void>}
*/
public push(message: NotificationModel): Promise<boolean> {
return Promise.resolve()
.then(() => {
if (message.iOSDevices != null && message.iOSDevices.length > 0) {
this.fcm.pushToiOS(message)
.catch(err => {
this.logger.error(err.message, err);
});
}
if (message.androidDevices != null && message.androidDevices.length > 0) {
this.fcm.pushToAndroid(message)
.catch(err => {
this.logger.error(err.message, err);
});
}
return true;
})
.catch((err) => {
this.logger.error(err.message, err);
return false;
});
}
/**
* Push notification to user
*
* @param userIds
* @param message
* @param type
* @returns {Bluebird<boolean>}
*/
public pushToUsers(userIds: string[] = [], message: NotificationModel, type?: string): Promise<boolean> {
if (userIds.length === 0) {
this.logger.info("Users are empty, nothing to push");
}
return Promise.each(userIds, (userId) => {
return this.device.getDevicesByUserId(userId)
.then(devices => {
if (devices != null && devices.length > 0) {
let allowPush: boolean = true;
if (allowPush) {
message.data.userId = userId;
this.pushToDevices(devices, message)
.catch(err => {
this.logger.error(err.message, err);
});
}
}
})
.catch(err => {
this.logger.error(err.message, err);
return true;
});
})
.then(() => {
return true;
});
}
/**
* Push notification to device
*
* @param devices
* @param message
* @returns {Bluebird<boolean>}
*/
public pushToDevices(devices: DeviceModel[] = [], message: NotificationModel): Promise<boolean> {
if (devices.length === 0) {
this.logger.info("Device list is empty, nothing to push");
return Promise.resolve(true);
}
message.iOSDevices = [];
message.androidDevices = [];
for (let device of devices) {
if (device.registrarId != null && device.registrarId !== "") {
if (device.deviceOs.toLowerCase() === DEVICE_OS.iOS.toLowerCase()) {
message.iOSDevices.push(device.registrarId);
} else if (device.deviceOs.toLowerCase() === DEVICE_OS.ANDROID.toLowerCase()) {
message.androidDevices.push(device.registrarId);
}
}
}
return this.push(message)
.catch(err => {
this.logger.error(err.message, err);
return false;
});
}
}
export default NotificationService;
import { UserPackageModel } from "./../models/user_package.model";
import { PackageDto } from "./../data/sql/models";
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { CollectionWrap, ExceptionModel, PackageModel } from "../models";
import { PackageRepository } from "../data";
import { BaseService, Log } from "./base.service";
import { ErrorCode, HttpStatus, logger as Logger } from "../libs";
import { DELETE_STATUS } from "../libs/constants";
import { injectable, inject } from "inversify";
/**
* Created by phuongho on 05/10/17.
*/
@injectable()
export class PackageService extends BaseService<PackageModel, PackageRepository> {
constructor(repo: PackageRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<PackageModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param data
* @param related
* @param filters
*/
public create(data: PackageModel, related = [], filters = []): Promise<PackageDto> {
let conditions: any = {};
conditions[Schema.PACKAGE_TABLE_SCHEMA.FIELDS.NAME] = data.name;
conditions[Schema.PACKAGE_TABLE_SCHEMA.FIELDS.IS_DELETED] = false;
return this.repo.findOneByAtribute({ conditions: conditions })
.then(object => {
if (object != null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.CODE,
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return this.insert(data);
});
}
}
export default PackageService;
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, PresentationModel, UserCodeModel, UserPackageModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ErrorCode, HttpStatus } from "../libs";
import { PresentationRepository, UserCodeRepository, UserPackageRepository } from "../data";
import { injectable, inject } from "inversify";
/**
* Created by phuongho on 05/10/17.
*/
@injectable()
export class PresentationService extends BaseService<PresentationModel, PresentationRepository> {
constructor(private userCode: UserCodeRepository,
private userPackage: UserPackageRepository,
repo: PresentationRepository,
@inject("Logger") log?: Log) {
super(repo, log);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<PresentationModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param Presentation
* @param related
* @param filters
*/
public create(obj: PresentationModel, related = [], filters = []): Promise<PresentationModel> {
let ret: any;
let userCode: UserCodeModel;
let userPackage: any;
let conditions: any = {};
conditions[Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.TITLE] = obj.title;
conditions[Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.USER_ID] = obj.userId;
conditions[Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.IS_DELETED] = false;
return this.repo.findOneByAtribute({ conditions: conditions })
.then((object) => {
if (object != null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.CODE,
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return this.userPackage.getInfoByUserId(obj.userId);
})
.then(object => {
if (object == null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.CONTRACT_NOT_FOUND.CODE,
ErrorCode.RESOURCE.CONTRACT_NOT_FOUND.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
} else {
userPackage = object;
}
return this.repo.countByQuery(q => {
q.where(Schema.PRESENTATION_TABLE_SCHEMA.FIELDS.USER_ID, obj.userId);
});
})
.then(totalFile => {
if (userPackage) {
if (totalFile >= userPackage.numberFile) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.MAXIMUM_CREATE_PRENSENTAION.CODE,
ErrorCode.RESOURCE.MAXIMUM_CREATE_PRENSENTAION.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
}
return this.userCode.findByCode(obj.userCode);
})
.then((object) => {
if (object == null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.USER_CODE_NOT_FOUND.CODE,
ErrorCode.RESOURCE.USER_CODE_NOT_FOUND.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
userCode = object;
return this.insert(obj);
})
.then(object => {
ret = object;
let userCodeModel = new UserCodeModel();
userCodeModel.id = userCode.id;
userCodeModel.isUsed = true;
return this.userCode.update(userCodeModel);
})
.then(object => {
return ret;
});
}
}
export default PresentationService;
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, RoleModel } from "../models";
import { DELETE_STATUS, ROLE } from "../libs/constants";
import { ErrorCode, HttpStatus, logger as Logger } from "../libs";
import { RoleRepository } from "../data";
import { injectable, inject } from "inversify";
/**
* Created by phuongho on 05/10/17.
*/
@injectable()
export class RoleService extends BaseService<RoleModel, RoleRepository> {
constructor(repo: RoleRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<RoleModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param role
* @param related
* @param filters
*/
public create(role: RoleModel, related = [], filters = []): Promise<RoleModel> {
let conditions: any = {};
conditions[Schema.ROLE_TABLE_SCHEMA.FIELDS.ID] = role.id;
conditions[Schema.ROLE_TABLE_SCHEMA.FIELDS.IS_DELETED] = false;
return this.repo.findOneByAtribute({ conditions: conditions })
.then(object => {
if (object != null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.CODE,
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return this.insert(role);
});
}
}
export default RoleService;
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import * as UUID from "uuid";
import * as firebase from "firebase-admin";
import * as momentTz from "moment-timezone";
import { BaseService, Log } from "./base.service";
import { ERROR_CODE, HTTP_STATUS, BearerObject, FirebaseAdmin, JsonWebToken } from "../libs";
import { ExceptionModel, SessionModel, UserModel, DeviceModel, } from "../models";
import { FIREBASE_ONLINE_STATUS } from "../libs/constants";
import { SessionRepository, UserRepository } from "../data";
import { injectable, inject } from "inversify";
/**
* Created by phuongho on 15/08/17.
*/
@injectable()
export class SessionService extends BaseService<SessionModel, SessionRepository> {
constructor(private user: UserRepository,
private firebase: FirebaseAdmin,
private jwt: JsonWebToken,
repo: SessionRepository,
@inject("Logger") log?: Log) {
super(repo, log);
}
public createFirebaseToken(userId: string, user?: UserModel, device?: DeviceModel): Promise<string> {
if (userId == null) {
return Promise.resolve(null);
}
let sdk = this.firebase.getInstance();
if (sdk == null) {
return Promise.reject(new ExceptionModel(
ERROR_CODE.OPERATION.FIREBASE_DISABLE.CODE,
ERROR_CODE.OPERATION.FIREBASE_DISABLE.MESSAGE,
false,
HTTP_STATUS.INTERNAL_SERVER_ERROR,
));
}
return Promise.resolve()
.then(() => {
if (user == null) {
return this.user.findOne(userId);
}
return user;
})
.tap((userModel) => {
sdk.auth().getUser(userId)
.catch(err => this.logger.warn("Account does not exist on Firebase, create one"))
.then((firebaseUser) => {
if (firebaseUser == null) {
return sdk.auth().createUser({
uid: userId,
email: userModel.email,
emailVerified: true,
displayName: `${userModel.firstName}`,
disabled: false,
});
}
})
.catch(err => {
this.logger.error(err.message, err);
return null;
});
})
.tap(userInfo => {
Promise.resolve(sdk.database()
.ref("/users")
.child(userInfo.id)
.update({
id: userInfo.id,
name: userInfo.firstName,
email: userInfo.email,
avatar: userInfo.avatarUrl != null ? userInfo.avatarUrl : "",
isReceivePushChat: true,
online: FIREBASE_ONLINE_STATUS.ONLINE,
updatedDate: firebase.database.ServerValue.TIMESTAMP
}))
.then(() => {
if (device != null && device.registrarId != null) {
return sdk.database()
.ref("/devices")
.child(userInfo.id)
.update({
[`${device.deviceId}`]: device.registrarId,
})
.catch(err => this.logger.error(err.message, err));
}
})
.catch(err => this.logger.error(err.message, err));
})
.then((firebaseUser) => {
return sdk.auth().createCustomToken(userId);
});
}
public create(userId: string, roleId: string, expire: number, deviceId: string, filters = []): Promise<SessionModel> {
if (userId == null || expire === 0 || deviceId == null) {
return Promise.reject(new ExceptionModel(
ERROR_CODE.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ERROR_CODE.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HTTP_STATUS.BAD_REQUEST
));
}
let current = Date.now();
let session = new SessionModel();
session.userId = userId;
session.roleId = roleId;
session.hash = UUID.v4();
session.expire = momentTz.tz(new Date(current + expire), "UTC");
session.token = this.jwt.encode(Object.assign({}, session), expire, deviceId);
return this.repo.insert(session)
.then((object) => {
return this.repo.findOne(object.id, null, filters);
});
}
public deleteSessionByUserId(userId: string, hash?: string, ignoreHashes?: string[]): Promise<any> {
if (userId != null) {
return this.repo.deleteByQuery(q => {
q.where(Schema.SESSION_TABLE_SCHEMA.FIELDS.USER_ID, userId);
if (hash != null) {
q.where(Schema.SESSION_TABLE_SCHEMA.FIELDS.HASH, hash);
}
if (ignoreHashes != null && ignoreHashes.length > 0) {
q.whereNotIn(Schema.SESSION_TABLE_SCHEMA.FIELDS.HASH, ignoreHashes);
}
});
}
return Promise.resolve(null);
}
public verifyToken(jwtObject: BearerObject, token: string): Promise<any> {
let exception;
if (token == null || token === "") {
exception = new ExceptionModel(ERROR_CODE.RESOURCE.INVALID_PARAMETER.CODE, ERROR_CODE.RESOURCE.INVALID_PARAMETER.MESSAGE, false);
exception.HTTP_STATUS = HTTP_STATUS.BAD_REQUEST;
return Promise.reject(exception);
}
let session;
return this.repo.findOneByQuery(q => {
q.where(Schema.SESSION_TABLE_SCHEMA.FIELDS.TOKEN, token);
q.andWhere(Schema.SESSION_TABLE_SCHEMA.FIELDS.USER_ID, jwtObject.userId);
})
.then(object => { // fix with reddit
if (object != null) {
session = object;
return this.user.findOne(object.userId);
}
return null;
})
.then(object => {
session.roleId = object.roleId;
return session;
})
.catch(err => {
return Promise.reject(err);
});
}
}
export default SessionService;
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, SettingModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ERROR_CODE, HTTP_STATUS } from "../libs";
import { SettingRepository } from "../data";
import { injectable, inject } from "inversify";
/**
* Created by phuongho on 05/10/17.
*/
@injectable()
export class SettingService extends BaseService<SettingModel, SettingRepository> {
constructor(repo: SettingRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<SettingModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param Setting
* @param related
* @param filters
*/
public create(setting: SettingModel, related = [], filters = []): Promise<SettingModel> {
let conditions: any = {};
conditions[Schema.SETTING_TABLE_SCHEMA.FIELDS.KEYWORD] = setting.keyword;
conditions[Schema.SETTING_TABLE_SCHEMA.FIELDS.IS_DELETED] = false;
return this.repo.findOneByAtribute({ conditions: conditions })
.then(object => {
if (object != null) {
return Promise.reject(new ExceptionModel(
ERROR_CODE.RESOURCE.DUPLICATE_RESOURCE.CODE,
ERROR_CODE.RESOURCE.DUPLICATE_RESOURCE.MESSAGE,
false,
HTTP_STATUS.NOT_FOUND,
));
}
return this.insert(setting);
});
}
}
export default SettingService;
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, TagModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ErrorCode, HttpStatus, logger as Logger } from "../libs";
import { TagRepository } from "../data";
import { injectable, inject } from "inversify";
/**
* Created by phuongho on 05/10/17.
*/
@injectable()
export class TagService extends BaseService<TagModel, TagRepository> {
constructor(repo: TagRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<TagModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param Tag
* @param related
* @param filters
*/
public create(tag: TagModel, related = [], filters = []): Promise<TagModel> {
let conditions: any = {};
conditions[Schema.TAG_TABLE_SCHEMA.FIELDS.NAME] = tag.name;
conditions[Schema.TAG_TABLE_SCHEMA.FIELDS.USER_ID] = tag.userId;
conditions[Schema.TAG_TABLE_SCHEMA.FIELDS.IS_DELETED] = false;
return this.repo.findOneByAtribute({ conditions: conditions })
.then(object => {
if (object != null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.CODE,
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return this.insert(tag);
});
}
}
export default TagService;
import { BaseService, Log } from "./base.service";
import { Utils } from "../libs";
import { injectable , inject} from "inversify";
@injectable()
export class TemplateService extends BaseService<any, any> {
constructor(@inject("Logger") log?: Log) {
super(null, log);
}
}
export default TemplateService;
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import * as _ from "lodash";
import * as firebase from "firebase-admin";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, UserTagModel, UserPackageModel, DeviceModel, ExceptionModel, SessionModel, UserModel } from "../models";
import { DELETE_STATUS, JWT_WEB_TOKEN, PASSWORD_LENGTH, PROPERTIES, ROLE } from "../libs/constants";
import { ErrorCode, HttpStatus, Utils, FirebaseAdmin, JsonWebToken, Mailer } from "../libs";
import { USER_TAG_TABLE_SCHEMA } from "./../data/sql/schema";
import {
DeviceRepository,
RoleRepository,
SessionRepository,
UserPackageRepository,
UserRepository,
UserTagRepository,
} from "../data";
import { injectable, inject } from "inversify";
@injectable()
export class UserService extends BaseService<UserModel, UserRepository> {
constructor(private device: DeviceRepository,
private firebase: FirebaseAdmin,
private jwt: JsonWebToken,
private mailer: Mailer,
private session: SessionRepository,
private userPackage: UserPackageRepository,
private userTag: UserTagRepository,
repo: UserRepository,
@inject("Logger") log?: Log) {
super(repo, log);
}
/**
* MOBILE verify email
* @param email
* @returns {Bluebird<boolean>}
*/
public verifyRegisterEmail(email: string): Promise<boolean> {
return Promise.resolve()
.then(() => {
return this.repo.findByEmail(email);
})
.then(user => {
if (user !== null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.EMAIL_IS_USED.CODE,
ErrorCode.RESOURCE.EMAIL_IS_USED.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return true;
});
}
/**
* Search User
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
* @returns {any}
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<UserModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* verifyLoginPrudential
* @param email
* @param password
* @param filters
* @returns {Bluebird<U>}
*/
public verifyLoginPrudential(email: string, password: string, filters = []): Promise<UserModel> {
return this.repo.findByEmail(email, ["role"], filters)
.then(object => {
if (object == null) {
return Promise.reject(new ExceptionModel(
ErrorCode.AUTHENTICATION.ACCOUNT_NOT_FOUND.CODE,
ErrorCode.AUTHENTICATION.ACCOUNT_NOT_FOUND.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
let isCorrect = Utils.compareHash(password, object.password);
if (isCorrect) {
return object;
}
return Promise.reject(new ExceptionModel(
ErrorCode.AUTHENTICATION.WRONG_USER_NAME_OR_PASSWORD.CODE,
ErrorCode.AUTHENTICATION.WRONG_USER_NAME_OR_PASSWORD.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
});
}
/**
* create User
* @param user
* @param related
* @param filters
* @returns {any}
*/
public create(user: UserModel, related = [], filters = []): Promise<UserModel> {
let userPackage: any;
user.password = Utils.hashPassword(user.password);
return Promise.resolve()
.then(() => {
if (user.parentId) {
return this.userPackage.getInfoByUserId(user.parentId);
}
return Promise.resolve(null);
})
.then((object) => {
if (object) {
userPackage = object;
}
if (user.parentId) {
return this.repo.countByQuery(q => {
q.where(Schema.USER_TABLE_SCHEMA.FIELDS.IS_DELETED, false);
q.where(Schema.USER_TABLE_SCHEMA.FIELDS.PARENT_ID, user.parentId);
});
}
})
.then((totalAccount) => {
if (totalAccount) {
if (totalAccount >= userPackage.numberAccount) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.MAXIMUM_CREATE_USER.CODE,
ErrorCode.RESOURCE.MAXIMUM_CREATE_USER.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
}
return this.verifyRegisterEmail(user.email);
})
.then(success => {
return this.insert(user);
})
.then(object => {
if (user.roleId === ROLE.PRESENTER) {
if (_.isArray(user.tags) && user.tags.length) {
user.tags.forEach(tagId => {
let obj = new UserTagModel();
obj.userId = object.id;
obj.tagId = tagId;
// insert user tag
this.userTag.insert(obj);
});
}
}
return object;
})
.then((object) => {
return this.findOne(object.id, related, filters);
});
}
/**
* remove user, update is_deleted = true, delete logic
* @param id
* @param related
* @param filters
* @returns {Bluebird<U>}
*/
public removeById(id: string, related = [], filters = []): Promise<boolean> {
return this.deleteLogic(id)
.then(object => {
// Clear session;
this.session.deleteByQuery(q => {
q.where(Schema.SESSION_TABLE_SCHEMA.FIELDS.USER_ID, object.id);
}).catch(err => {
this.logger.error(err.message, err);
});
// Clear device;
this.device.deleteByQuery(q => {
q.where(Schema.DEVICE_TABLE_SCHEMA.FIELDS.USER_ID, object.id);
}).catch(err => {
this.logger.error(err.message, err);
});
return true;
});
}
/**
* full update
* @param user
* @param related(optional)
* @param filters(optional)
* @returns {any}
*/
public update(user: UserModel, related = [], filters = []): Promise<any> {
return this.findById(user.id, related, filters)
.then(object => {
if (!object || object.isDeleted) {
throw new ExceptionModel(
ErrorCode.AUTHENTICATION.ACCOUNT_NOT_FOUND.CODE,
ErrorCode.AUTHENTICATION.ACCOUNT_NOT_FOUND.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
);
}
if (user.password) {
if (!Utils.validatePassword(user.password)) {
throw new ExceptionModel(
ErrorCode.AUTHENTICATION.ACCOUNT_NOT_FOUND.CODE,
ErrorCode.AUTHENTICATION.ACCOUNT_NOT_FOUND.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
);
}
user.password = Utils.hashPassword(user.password);
}
if (user.email && user.email !== object.email) {
if (!Utils.validateEmail(user.email)) {
throw new ExceptionModel(
ErrorCode.RESOURCE.INVALID_EMAIL_FORMAT.CODE,
ErrorCode.RESOURCE.INVALID_EMAIL_FORMAT.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
);
}
return this.repo.findByEmail(user.email)
.then(obj => {
if (obj) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.EMAIL_IS_USED.CODE,
ErrorCode.RESOURCE.EMAIL_IS_USED.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return Promise.resolve(object);
});
} else {
return Promise.resolve(object);
}
})
.then(object => {
return this.repo.update(user);
})
.tap(object => {
// delete all user tag
return this.userTag.deleteByQuery(q => {
q.where(Schema.USER_TAG_TABLE_SCHEMA.FIELDS.USER_ID, user.id);
});
})
.then((object) => {
if (user.roleId === ROLE.PRESENTER) {
if (_.isArray(user.tags) && user.tags.length) {
user.tags.forEach(tagId => {
let obj = new UserTagModel();
obj.userId = user.id;
obj.tagId = tagId;
// insert user tag
this.userTag.insert(obj);
});
}
}
return this.findById(user.id);
})
.tap((userInfo) => {
if (this.firebase.getInstance() != null) {
this.firebase.getInstance()
.database()
.ref("/users")
.child(userInfo.id)
.update({
id: userInfo.id,
name: userInfo.firstName,
email: userInfo.email,
avatar: userInfo.avatarUrl != null ? userInfo.avatarUrl : "",
updatedDate: firebase.database.ServerValue.TIMESTAMP
})
.catch(err => this.logger.error(err.message, err));
}
});
}
/**
* forgotPassword
* @param email
* @param url
* @returns {Bluebird<boolean>}
*/
public forgotPassword(email: string, url: string): Promise<boolean> {
return Promise.resolve()
.then(() => {
return this.repo.findByEmail(email);
})
.then((object) => {
if (object === null) {
return Promise.reject(new ExceptionModel(
ErrorCode.AUTHENTICATION.ACCOUNT_NOT_FOUND.CODE,
ErrorCode.AUTHENTICATION.ACCOUNT_NOT_FOUND.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
let token = this.jwt.encode({ userId: object.id }, JWT_WEB_TOKEN.RESET_PASSWORD_TIME_EXPIRED, JsonWebToken.DEFAULT_CLIENT);
let link = `${url}/${token}`;
// send mail reset password
this.mailer.sendResetPassword(object, link);
return true;
});
}
/**
* set password when reset password
* @param userId
* @param newPassword
* @param related
* @param filters
*/
public setPassword(userId: string, newPassword: string, related = [], filters = []): Promise<boolean> {
return this.repo.findOne(userId)
.then(user => {
if (user === null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.NOT_FOUND.CODE,
ErrorCode.RESOURCE.NOT_FOUND.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
} else {
user.password = Utils.hashPassword(newPassword);
return this.repo.update(user);
}
})
.then(user => {
// Clear session;
this.session.deleteByQuery(q => {
q.where(Schema.SESSION_TABLE_SCHEMA.FIELDS.USER_ID, userId);
}).catch(err => {
this.logger.error(err.message, err);
});
// Clear device;
this.device.deleteByQuery(q => {
q.where(Schema.DEVICE_TABLE_SCHEMA.FIELDS.USER_ID, userId);
}).catch(err => {
this.logger.error(err.message, err);
});
return user;
});
}
/**
* change password
* @param userId
* @param oldPassword
* @param newPassword
* @param related
* @param filters
* @returns {Bluebird<U>}
*/
public changePassword(userId: string, oldPassword: string, newPassword: string, related = [], filters = []) {
return this.findById(userId)
.then(user => {
if (user === null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.NOT_FOUND.CODE,
ErrorCode.RESOURCE.NOT_FOUND.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
} else {
if (Utils.compareHash(oldPassword, user.password) === false) {
return Promise.reject(new ExceptionModel(
ErrorCode.AUTHENTICATION.WRONG_PASSWORD.CODE,
ErrorCode.AUTHENTICATION.WRONG_PASSWORD.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
} else if (Utils.compareHash(oldPassword, Utils.hashPassword(newPassword)) === true) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.PASSWORD_USE_BEFORE.CODE,
ErrorCode.RESOURCE.PASSWORD_USE_BEFORE.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
} else {
user.password = Utils.hashPassword(newPassword);
return this.repo.update(user);
}
}
})
.then(user => {
// Clear session;
this.session.deleteByQuery(q => {
q.where(Schema.SESSION_TABLE_SCHEMA.FIELDS.USER_ID, userId);
}).catch(err => {
this.logger.error(err.message, err);
});
// Clear device;
this.device.deleteByQuery(q => {
q.where(Schema.DEVICE_TABLE_SCHEMA.FIELDS.USER_ID, userId);
}).catch(err => {
this.logger.error(err.message, err);
});
return user;
})
.then(object => {
return this.findById(userId, ["role"], ["password", "isDeleted"]);
});
}
/**
* Update My Profile
* @param user
* @param related
* @param filters
* @returns {Bluebird<U>}
*/
public updateMyProfile(user: UserModel, related = [], filters = []): Promise<UserModel> {
return this.repo.update(user)
.then((object) => {
return this.findById(object.id, related, filters);
})
.tap((userInfo) => {
if (this.firebase.getInstance() != null) {
this.firebase.getInstance()
.database()
.ref("/users")
.child(userInfo.id)
.update({
avatar: userInfo.avatarUrl != null ? userInfo.avatarUrl : "",
createdDate: firebase.database.ServerValue.TIMESTAMP,
email: userInfo.email,
firstName: userInfo.firstName,
id: userInfo.id,
lastName: userInfo.lastName,
online: false,
phoneNumber: userInfo.phone != null ? userInfo.phone : "",
updatedDate: firebase.database.ServerValue.TIMESTAMP
})
.catch(err => this.logger.error(err.message, err));
}
});
}
}
export default UserService;
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, UserCodeModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ErrorCode, HttpStatus, logger as Logger } from "../libs";
import { UserCodeRepository } from "../data";
import { injectable, inject } from "inversify";
/**
* Created by phuongho on 05/10/17.
*/
@injectable()
export class UserCodeService extends BaseService<UserCodeModel, UserCodeRepository> {
constructor(repo: UserCodeRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<UserCodeModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param UserCode
* @param related
* @param filters
*/
public create(obj: UserCodeModel, related = [], filters = []): Promise<UserCodeModel> {
let conditions: any = {};
conditions[Schema.USER_CODE_TABLE_SCHEMA.FIELDS.NAME] = obj.name;
conditions[Schema.USER_CODE_TABLE_SCHEMA.FIELDS.USER_ID] = obj.userId;
conditions[Schema.USER_CODE_TABLE_SCHEMA.FIELDS.IS_DELETED] = false;
return this.repo.findOneByAtribute({ conditions: conditions })
.then(object => {
if (object != null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.CODE,
ErrorCode.RESOURCE.DUPLICATE_RESOURCE.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return this.insert(obj);
});
}
}
export default UserCodeService;
/**
* Created by phuongho on 05/10/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, UserPackageModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ErrorCode, HttpStatus, logger as Logger } from "../libs";
import { PackageRepository, UserPackageRepository } from "../data";
import { injectable, inject } from "inversify";
@injectable()
export class UserPackageService extends BaseService<UserPackageModel, UserPackageRepository> {
constructor(private pack: PackageRepository, repo: UserPackageRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<UserPackageModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param data
* @param related
* @param filters
*/
public create(data: UserPackageModel, related = [], filters = []): Promise<UserPackageModel> {
return this.pack.findById(data.packageId)
.then(object => {
if (object === null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.NOT_FOUND.CODE,
ErrorCode.RESOURCE.NOT_FOUND.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
data.numberAccount = object.numberAccount;
data.numberFile = object.numberFile;
data.price = object.price;
return this.insert(data);
});
}
}
export default UserPackageService;
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, UserPresentationModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ErrorCode, HttpStatus, logger as Logger } from "../libs";
import { PresentationRepository, UserPresentationRepository } from "../data";
import { injectable, inject } from "inversify";
@injectable()
export class UserPresentationService extends BaseService<UserPresentationModel, UserPresentationRepository> {
constructor(private present: PresentationRepository, repo: UserPresentationRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<UserPresentationModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param data
* @param related
* @param filters
*/
public create(data: UserPresentationModel, related = [], filters = []): Promise<UserPresentationModel> {
return this.present.findById(data.presentationId)
.then(object => {
if (object === null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.NOT_FOUND.CODE,
ErrorCode.RESOURCE.NOT_FOUND.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return this.insert(data);
});
}
}
export default UserPresentationService;
import * as Promise from "bluebird";
import * as Schema from "../data/sql/schema";
import { BaseService, Log } from "./base.service";
import { CollectionWrap, ExceptionModel, UserTagModel } from "../models";
import { DELETE_STATUS } from "../libs/constants";
import { ErrorCode, HttpStatus } from "../libs";
import { TagRepository, UserTagRepository } from "../data";
import { injectable, inject } from "inversify";
@injectable()
export class UserTagService extends BaseService<UserTagModel, UserTagRepository> {
constructor(private tag: TagRepository, repo: UserTagRepository, @inject("Logger") log?: Log) {
super(repo, log);
}
/**
* @param searchParams
* @param offset
* @param limit
* @param related
* @param filters
*/
public search(searchParams: any, offset?: number, limit?: number, related = [], filters = []): Promise<CollectionWrap<UserTagModel>> {
return this.repo.search(searchParams, offset, limit, related, filters);
}
/**
* @param data
* @param related
* @param filters
*/
public create(data: UserTagModel, related = [], filters = []): Promise<UserTagModel> {
return this.tag.findById(data.tagId)
.then(object => {
if (object === null) {
return Promise.reject(new ExceptionModel(
ErrorCode.RESOURCE.NOT_FOUND.CODE,
ErrorCode.RESOURCE.NOT_FOUND.MESSAGE,
false,
HttpStatus.NOT_FOUND,
));
}
return this.insert(data);
});
}
}
export default UserTagService;
import { Container } from "inversify";
// import {
// ApplicationRepository,
// AssignPresentationRepository,
// DeviceRepository,
// LanguageRepository,
// MediaRepository,
// PackageRepository,
// PresentationRepository,
// RoleRepository,
// SessionRepository,
// SettingRepository,
// TagRepository,
// UserCodeRepository,
// UserPackageRepository,
// UserPresentationRepository,
// UserTagRepository,
// UserRepository,
// } from "./data";
// import {
// } from "./interactors";
export const IoC = new Container();
export default IoC;
import * as fs from "fs";
import * as yaml from "js-yaml";
import * as path from "path";
const loadSetting = (): any => {
let conf = {};
let url = path.join(__dirname, "configs");
if (process.env.NODE_ENV == null) {
process.env.NODE_ENV = "development";
}
try {
let doc = yaml.safeLoad(fs.readFileSync(`${url}/${process.env.NODE_ENV}.yaml`, "utf8"));
for (let key of Object.keys(doc)) {
let val = doc[key];
if (val != null) {
conf[key] = val;
}
}
} catch (err) {
console.log(`Error when loading configuration file ${process.env.NODE_ENV}.yaml, fallback to configuration.yaml`);
try {
let doc = yaml.safeLoad(fs.readFileSync(`${url}/configuration.yaml`, "utf8"));
for (let key of Object.keys(doc)) {
let val = doc[key];
if (val != null) {
conf[key] = val;
}
}
} catch (err) {
console.log(`Error when loading configuration file configuration.yaml, using default value for each module: ${err.message}`);
}
}
return conf;
};
module.exports = {
client: "postgresql",
connection: loadSetting().database.postgres,
pool: {
min: 2,
max: 10
},
migrations: {
directory: "./data/sql/migrations"
},
seeds: {
directory: "./data/sql/seed"
}
};
/**
* Created by phuongho on 15/08/17.
*/
import * as fs from "fs";
import * as yaml from "js-yaml";
import * as path from "path";
// export interface SMSOption {
// accountSid: string;
// authToken: string;
// area: string;
// sender: string;
// force: boolean;
// sandbox: boolean;
// sendEmail: boolean;
// }
// export interface GatewayPayment {
// merchantId: string;
// publicKey: string;
// privateKey: string;
// }
// export interface StorageOption {
// awsBucketName: string;
// opts: any;
// }
// export interface FCMOption {
// serverKey: string;
// }
export class Config {
public static loadSetting(): any {
let conf = {};
let url = path.join(__dirname, "..", "configs");
if (process.env.NODE_ENV == null) {
process.env.NODE_ENV = "development";
}
try {
let doc = yaml.safeLoad(fs.readFileSync(`${url}/${process.env.NODE_ENV}.yaml`, "utf8"));
for (let key of Object.keys(doc)) {
let val = doc[key];
if (val != null) {
conf[key] = val;
}
}
} catch (err) {
console.log(`Error when loading configuration file ${process.env.NODE_ENV}.yaml, fallback to configuration.yaml`);
try {
let doc = yaml.safeLoad(fs.readFileSync(`${url}/configuration.yaml`, "utf8"));
for (let key of Object.keys(doc)) {
let val = doc[key];
if (val != null) {
conf[key] = val;
}
}
} catch (err) {
console.log(`Error when loading configuration file configuration.yaml, using default value for each module: ${err.message}`);
}
}
return conf;
}
}
export default Config;
/**
* Created by phuongho on 15/08/17.
*/
export const IS_FORCE = true;
/**
* Define time-zone default
*/
export const TIME_ZONE = {
TIME_ZONE_DEFAULT: "Asia/Singapore",
TIME_ZONE_VN: "Asia/Ho_Chi_Minh",
TIME_ZONE_UTC: "UTC",
};
export const EXTENDED_HEADER = {
HEADER_TOTAL: "Total",
HEADER_OFFSET: "Offset",
HEADER_LIMIT: "Limit",
};
export const JWT_WEB_TOKEN = {
DEFAULT_ISSUER: "vivis",
DEFAULT_CLIENT: "simulator",
DEFAULT_EXPIRE: 365 * 24 * 60 * 60 * 1000, // 1 year,
RESET_PASSWORD_TIME_EXPIRED: 60 * 60 * 1000, // 60 minutes
PIN_TIME_EXPIRED: 5 * 60 * 1000, // 60 minutes
};
export const HEADERS = {
AUTHORIZATION: "authorization",
USER_AGENT: "user-agent",
DEVICE_ID: "device-id",
REGISTRAR_ID: "registrar-id",
DEVICE_OS: "device-os",
DEVICE_NAME: "device-name",
DEVICE_MODEL: "device-model",
OS_VERSION: "os-version",
APP_VERSION: "app-version",
BUILD_VERSION: "build-version"
};
export const PLATFORM = {
IOS: "iOS",
ANDROID: "Android",
WEB_PORTAL: "web-portal",
WEB_RESIDENT: "web-resident"
};
export const DELETE_STATUS = {
YES: true,
NO: false,
};
export const PASSWORD_LENGTH = 6;
export const PROPERTIES = {
MOBILE_USER_AGENT: "mobile",
HEADER_TOTAL: "Total",
HEADER_OFFSET: "Offset",
HEADER_LIMIT: "Limit",
COLUMN_TOTAL_ITEMS: "total"
};
export const ROLE = {
SYSTEM_ADMIN: "system_admin",
MANAGER: "manager",
COMPANY_ADMIN: "company_admin",
OPERATOR: "operator",
PRESENTER: "presenter",
USER: "user"
};
/**
* TODO: Must be changed in the future.
* All message will be defined and will be moved to another class in the future.
*/
export const MESSAGE_INFO = {
MI_TITLE_MESSAGE: "message",
MI_CREATE_SUCCESSFUL: "create successful.",
MI_CREATE_UNSUCCESSFUL: "create unsuccessful.",
MI_UPDATE_SUCCESSFUL: "update successful.",
MI_UPDATE_UNSUCCESSFUL: "update unsuccessful.",
MI_DELETE_SUCCESSFUL: "delete successful.",
MI_DELETE_UNSUCCESSFUL: "delete unsuccessful.",
MI_IMPORT_SUCCESSFUL: "import successful.",
MI_EXPORT_SUCCESSFUL: "export successful.",
MI_UPLOAD_SUCCESSFUL: "upload successful.",
MI_SENT_SUCCESSFUL: "sent successful.",
MI_CHANGE_PW_SUCCESSFUL: "change password successful.",
MI_SEND_PIN_SUCCESSFUL: "send pin successful.",
MI_SEND_PIN_UN_SUCCESSFUL: "send pin unsuccessful.",
MI_PHONE_INVALID: "phone number invalid",
MI_APPLY_PIN_SUCCESSFUL: "apply pin successful.",
MI_RESET_PIN_SUCCESSFUL: "reset pin successful.",
MI_SEND_MAIL_CONTACT_US_SUCCESSFUL: "send contact us successful.",
MI_APPLY_VERIFY_PHONE_CODE_SUCCESSFUL: "verify phone successful.",
MI_RESET_VERIFY_PHONE_CODE_SUCCESSFUL: "reset verify phone code successful.",
MI_ASSIGN_USER_SUCCESSFUL: "assign user successful.",
MI_RESET_PASSWORD_EXPIRED: "your reset token was expired.",
MI_CHECK_EMAIL_FOR_NEW_PASSWORD: "check your email for new password.",
MI_CHECK_PHONE_FOR_GET_VERIFY_CODE: "check your phone to get verify code.",
MI_RESET_PASSWORD_TOKEN_INVALID: "your token is invalid.",
MI_CREATE_ORDER_SUCCESSFUL: "your order has created successful.",
MI_RESET_PASSWORD_SUCCESSFUL: "we will send an email to your primary email user_address that you can use to reset your password.",
MI_SMS_SEND_ACCESS_CODE: "your vivis verification code is:",
MI_SMS_RESEND_ACCESS_CODE: "your vivis new verification code is:",
MI_SMS_SEND_VERIFY_PHONE_CODE: "your verify phone code is:",
MI_SMS_RESEND_VERIFY_PHONE_CODE: "your new verify phone code is:",
MI_CREATE_PAYMENT_SUCCESSFUL: "your payment has been completed",
MI_REJECT_SUCCESSFUL: "reject request unit successful.",
MI_REJECT_UN_SUCCESSFUL: "reject request unit unsuccessful.",
MI_CANCEL_UNIT_SUCCESSFUL: "cancel unit successful.",
MI_CANCEL_UNIT_UN_SUCCESSFUL: "cancel unit unsuccessful.",
MI_BULK: (totalSuccess, totalFail, failIndex?): string => {
if (failIndex) {
return `${totalSuccess} success. ${totalFail} fail at line ${failIndex}`;
}
return `${totalSuccess} success. ${totalFail} fail`;
},
MI_REMARK_HAS_MASTER: (roleId): string => {
return `Unit has existing master ${roleId}`;
},
MI_LIKE_SUCCESSFUL: "like successful.",
MI_UNLIKE_SUCCESSFUL: "unlike successful.",
};
export const NOTIFICATION_OPTIONS = {
DEFAULT_TITLE: "Attention",
DEFAULT_MESSAGE: "You have new message",
DEFAULT_COLLAPSE_KEY: "default",
DEFAULT_ICON: "ic_launcher",
DEFAULT_EXPIRE: 2419200, // 4 weeks
DEFAULT_SOUND: "default",
PRIORITY: {
HIGH: {
VALUE: "high",
ANDROID: "high",
IOS: 10,
},
NORMAL: {
VALUE: "normal",
ANDROID: "normal",
IOS: 5,
},
}
};
export const DEVICE_OS = {
iOS: "iOS",
ANDROID: "Android"
};
/**
* firebase - online status: channel or online or offline.
*/
export const FIREBASE_ONLINE_STATUS = {
ONLINE: "online",
OFFLINE: "offline"
};
export const EMAIL_TEMPLATE = {
RESET_PASSWORD: "1h_reset_password",
NEW_PASSWORD: "1k_new_password",
SEND_CUSTOM_EMAIL: "send_custom_email"
};
export const CURRENCY = {
SINGAPORE: "sgd"
};
export const MOMENT_DATE_FORMAT = {
YYYY_MM_DD: "YYYY-MM-DD",
DD_MMM_YY: "DD MMM YY",
DD_MMM_YY_H_m: "DD MMM YY HH:mm",
MM_DD_YYYY: "MM-DD-YYYY",
DD_MM_YYYY: "DD-MM-YYYY",
YYYY_MM_DD_H_m: "YYYY-MM-DD HH:mm",
MM_DD_YYYY_H_m: "MM-DD-YYYY HH:m",
DD_MM_YYYY_H_m: "DD-MM-YYYY HH:mm",
DD_MMMM_YYYY_hh_mm_A: "DD MMMM YYYY, hh:mm A",
HH_MM: "HH:mm",
HH_MM_A: "hh:mm a",
SEND_MAIL_FULL_DATE: "dddd, DD MMM YYYY",
MMM_YY: "MMM YY",
SEND_MAIL_FULL_DATE_TIME: "hh:mm a, dddd, DD MMM YYYY"
};
\ No newline at end of file
/**
* Created by phuongho on 15/08/17.
*/
class Code {
public readonly CODE;
public readonly MESSAGE;
constructor(code, message) {
this.CODE = code;
this.MESSAGE = message;
}
}
export const ErrorCode = {
UNKNOWN: {
TYPE: "Unknown.",
GENERIC: new Code(0, "Intern al Server Error."),
NOT_IMPLEMENT: new Code(1, "Not Implement ExceptionModel"),
UPGRADE_NEEDED: new Code(2, "Please update new version"),
MAINTENANCE_PERIOD: new Code(3, "Maintenance period"),
APOCALYPSE: new Code(13, "The world is end"),
},
RESOURCE: {
TYPE: "Resource.",
GENERIC: new Code(1000, "unknown Resource's Error."),
INVALID_URL: new Code(1001, "invalid url."),
NOT_FOUND: new Code(1002, "the item has been deleted"),
DUPLICATE_RESOURCE: new Code(1003, "resource was already existed."),
INVALID_REQUEST: new Code(1004, "invalid request."),
EMPTY_EMAIL: new Code(1005, "email can't be empty."),
INVALID_EMAIL_FORMAT: new Code(1006, "invalid email format."),
INVALID_PASSWORD: new Code(1007, "password must be at least 6 characters."),
EMAIL_IS_USED: new Code(1008, "email was used."),
MISSING_REQUIRED_FIELDS: new Code(1010, "missing required fields."),
INVALID_PARAMETER: new Code(1011, "invalid parameter."),
PASSWORD_USE_BEFORE: new Code(1012, "you can't use a password you have used before."),
INVALID_PHONE_NUMBER: new Code(1013, "the phone number format is incorrect"),
INVALID_DATE_TYPE: new Code(1066, "invalid date type"),
INVALID_COUNTRY_CODE: new Code(1067, "invalid code"),
MAXIMUM_CREATE_PRENSENTAION: new Code(1068, "you've reached the maximum number of presentations associated with this your account."),
MAXIMUM_CREATE_USER: new Code(1069, "you've reached the maximum number of users associated with this your account."),
USER_CODE_NOT_FOUND: new Code(1070, "the code doest not exist."),
CONTRACT_NOT_FOUND: new Code(1071, "the contract doest not exist."),
INVALID_FILE_UPLOAD: new Code(1072, "invalid file upload."),
},
AUTHENTICATION: {
TYPE: "Authentication.",
GENERIC: new Code(1100, "unknown authentication's error."),
VIOLATE_RFC6750: new Code(1101, "RFC6750 states the access_token MUST NOT be provided in more than one place in a single request."),
TOKEN_NOT_FOUND: new Code(1102, "token not found."),
INVALID_AUTHORIZATION_HEADER: new Code(1103, "invalid authorization header."),
ACCOUNT_NOT_FOUND: new Code(1104, "account not found."),
WRONG_USER_NAME_OR_PASSWORD: new Code(1105, "wrong user name or password."),
WRONG_PASSWORD: new Code(1105, "you have entered the wrong password."),
INVALID_TOKEN: new Code(1106, "invalid token."),
TOKEN_EXPIRE: new Code(1107, "token expired."),
NEED_ACCESS_CODE: new Code(1108, "access code is needed."),
INVALID_CODE: new Code(1109, "invalid access code."),
ALREADY_ACTIVE: new Code(1110, "account has already activated."),
NEED_ACTIVE: new Code(1112, "account has not activated."),
ALREADY_VERIFY_PHONE: new Code(1113, "your phone code already verified. Pls resend new pin code"),
INVALID_VERIFY_PHONE_CODE: new Code(1114, "the verification code entered is invalid"),
VERIFY_PHONE_CODE_EXPIRE: new Code(1115, "verify phone code expired."),
LIMIT_QUOTA: new Code(1116, "you have reached the maximum number of verification limit"),
},
PRIVILEGE: {
TYPE: "Privilege",
GENERIC: new Code(1200, "unknown privilege's error."),
NOT_ALLOW: new Code(1201, "you do not have permission to access."),
NOT_ALLOW_CONDO_LESS: new Code(1202, "you do not have a condo to access."),
SUPPORT_ONLY_FOR_RESIDENT_USER: new Code(1203, "you are currently registered as a non resident \nbooking of facilities is only available to condo residents \nplease contact your condo manager for more information \nthank you"),
INVALID_VERSION: new Code(1204, "invalid version format"),
VERSION_NOT_FOUND: new Code(1205, "version not found"),
FORCE_UPDATE: new Code(1206, "need update version")
},
PAYMENT: {
TYPE: "PAYMENT",
GENERIC: new Code(1300, "unknown braintree's error."),
TYPE_PAYMENT_INVALID: new Code(1301, "payment type invalid"),
PAYMENT_INVALID: new Code(1302, "The payment invalid."),
WRONG_BILLING_DETAIL: new Code(1303, "Invalid billing detail. Please booking again."),
MISSING_CUSTOMER_ID: new Code(1304, "Missing customerId"),
STRIPE_KEY_INVALID: new Code(1308, "Invalid Stripe key")
},
OPERATION: {
TYPE: "OPEATION",
GENERIC: new Code(1400, "Unknown error."),
FIREBASE_DISABLE: new Code(1401, "Firebase was disable"),
PAYMENT_DISABLE: new Code(1402, "Payment was disable"),
}
};
export default ErrorCode;
/**
* Created by phuongho on 15/08/17.
*/
import * as FCM from "fcm-node";
import * as Promise from "bluebird";
import { logger as Logger } from "../libs";
import { NOTIFICATION_OPTIONS } from "../libs/constants";
import { NotificationModel } from "../models";
export class FCMPush {
private opts: any = {};
private fcm: FCM;
constructor(opts: any) {
this.opts = opts != null ? {...opts} : {};
this.fcm = new FCM(this.opts.serverKey);
}
/**
* Function push notification to iOS devices.
* @param message
* @returns {any}
*/
public pushToiOS(message: NotificationModel): Promise<boolean> {
if (message == null || this.fcm == null) {
return Promise.resolve(true);
}
return Promise.resolve()
.then(() => {
let msg = {
registration_ids: message.iOSDevices,
content_available: message.contentAvailable,
priority: message.priority === NOTIFICATION_OPTIONS.PRIORITY.HIGH.VALUE ? NOTIFICATION_OPTIONS.PRIORITY.HIGH.IOS : NOTIFICATION_OPTIONS.PRIORITY.NORMAL.IOS,
notification: {
title: message.title,
body: message.body,
click_action: message.clickAction,
icon: message.icon,
badge: message.badge,
sound: message.sound,
},
time_to_live: message.expire,
data: message.data
};
this.fcm.send(msg, function (err, response) {
if (err) {
Logger.error("Sent to iOS devices: " + err, err);
} else {
Logger.info("Successfully sent to iOS devices with response: " + response, response);
}
});
return true;
})
.catch((err) => {
Logger.error(err.message, err);
return false;
});
}
/**
* Function push notification to Android devices.
* @param message
* @returns {any}
*/
public pushToAndroid(message: NotificationModel): Promise<boolean> {
if (message == null || this.fcm == null) {
return Promise.resolve(true);
}
return Promise.resolve()
.then(() => {
let msg = {
registration_ids: message.androidDevices,
content_available: message.contentAvailable,
priority: message.priority === NOTIFICATION_OPTIONS.PRIORITY.HIGH.VALUE ? NOTIFICATION_OPTIONS.PRIORITY.HIGH.ANDROID : NOTIFICATION_OPTIONS.PRIORITY.NORMAL.ANDROID,
// notification: {
// title: message.title,
// body: message.body,
// click_action: message.clickAction,
// icon: message.icon,
// badge: message.badge,
// sound: message.sound,
// },
time_to_live: message.expire,
data: {
title: message.title,
body: message.body,
clickAction: message.clickAction,
fromFCM: message.data.fromFCM,
type: message.data.type,
itemId: message.data.itemId,
userId: message.data.userId
}
};
this.fcm.send(msg, function (err, response) {
if (err) {
Logger.error("Sent to Android devices: " + err, err);
} else {
Logger.info("Successfully sent to Android devices with response: " + response, response);
}
});
return true;
})
.catch((err) => {
Logger.error(err.message, err);
return false;
});
}
}
export default FCMPush;
import * as sdk from "firebase-admin";
import * as _ from "lodash";
import * as path from "path";
import * as fs from "fs";
import { logger as Logger } from "./index";
interface FirebaseOpts {
file: string;
database: string;
}
export class FirebaseAdmin {
private opts: FirebaseOpts;
private instance: sdk.app.App;
constructor(opts: any) {
opts = opts || {};
let defaultConf: FirebaseOpts = {
file: "firebase.json",
database: "https://vivis-dev.firebaseio.com",
};
this.opts = _.defaultsDeep(opts, defaultConf) as FirebaseOpts;
let url = path.join(__dirname, "..", "configs", this.opts.file);
if (fs.existsSync(url)) {
this.instance = sdk.initializeApp({
credential: sdk.credential.cert(require(url)),
databaseURL: this.opts.database,
});
} else {
Logger.warn(`Firebase config file - ${this.opts.file} does not exist, skip`);
this.instance = null;
}
}
public getInstance(): sdk.app.App {
return this.instance;
}
}
export default FirebaseAdmin;
/**
* Created by phuongho on 15/08/17.
*/
export class HttpCode {
public static readonly ACCEPTED = 202;
public static readonly BAD_GATEWAY = 502;
public static readonly BAD_REQUEST = 400;
public static readonly CONFLICT = 409;
public static readonly CONTINUE = 100;
public static readonly CREATED = 201;
public static readonly EXPECTATION_FAILED = 417;
public static readonly FAILED_DEPENDENCY = 424;
public static readonly FORBIDDEN = 403;
public static readonly GATEWAY_TIMEOUT = 504;
public static readonly GONE = 410;
public static readonly HTTP_VERSION_NOT_SUPPORTED = 505;
public static readonly INSUFFICIENT_SPACE_ON_RESOURCE = 419;
public static readonly INSUFFICIENT_STORAGE = 507;
public static readonly INTERNAL_SERVER_ERROR = 500;
public static readonly LENGTH_REQUIRED = 411;
public static readonly LOCKED = 423;
public static readonly METHOD_FAILURE = 420;
public static readonly METHOD_NOT_ALLOWED = 405;
public static readonly MOVED_PERMANENTLY = 301;
public static readonly MOVED_TEMPORARILY = 302;
public static readonly MULTI_STATUS = 207;
public static readonly MULTIPLE_CHOICES = 300;
public static readonly NETWORK_AUTHENTICATION_REQUIRED = 511;
public static readonly NO_CONTENT = 204;
public static readonly NON_AUTHORITATIVE_INFORMATION = 203;
public static readonly NOT_ACCEPTABLE = 406;
public static readonly NOT_FOUND = 404;
public static readonly NOT_IMPLEMENTED = 501;
public static readonly NOT_MODIFIED = 304;
public static readonly OK = 200;
public static readonly PARTIAL_CONTENT = 206;
public static readonly PAYMENT_REQUIRED = 402;
public static readonly PRECONDITION_FAILED = 412;
public static readonly PRECONDITION_REQUIRED = 428;
public static readonly PROCESSING = 102;
public static readonly PROXY_AUTHENTICATION_REQUIRED = 407;
public static readonly REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
public static readonly REQUEST_TIMEOUT = 408;
public static readonly REQUEST_TOO_LONG = 413;
public static readonly REQUEST_URI_TOO_LONG = 414;
public static readonly REQUESTED_RANGE_NOT_SATISFIABLE = 416;
public static readonly RESET_CONTENT = 205;
public static readonly SEE_OTHER = 303;
public static readonly SERVICE_UNAVAILABLE = 503;
public static readonly SWITCHING_PROTOCOLS = 101;
public static readonly TEMPORARY_REDIRECT = 307;
public static readonly TOO_MANY_REQUESTS = 429;
public static readonly UNAUTHORIZED = 401;
public static readonly UNPROCESSABLE_ENTITY = 422;
public static readonly UNSUPPORTED_MEDIA_TYPE = 415;
public static readonly USE_PROXY = 305;
}
export default HttpCode;
/**
* Created by phuongho on 15/08/17.
*/
import { Config } from "./config";
import { ErrorCode as ERROR_CODE } from "./error_code";
import { ExceptionModel } from "../models";
import { FCMPush } from "./fcm";
import { FirebaseAdmin } from "./firebase";
import { HttpCode as HTTP_STATUS } from "./http_code";
import { I18N, Language } from "./languages";
import { JsonWebToken } from "./jwt";
import { Logger, Log } from "./logger";
import { Mailer } from "./mailer";
import { SMS, Response, LookupResponse } from "./sms";
import { Scheduler } from "./scheduler";
import { Stripe } from "./stripe";
import { Uploader } from "./uploader";
// Utils and classes
export * from "./mapper";
export * from "./moment_range";
export * from "./utils";
export { ErrorCode as ERROR_CODE } from "./error_code";
export { FCMPush } from "./fcm";
export { FirebaseAdmin } from "./firebase";
export { HttpCode as HTTP_STATUS } from "./http_code";
export { I18N, Language } from "./languages";
export { JsonWebToken, BearerObject } from "./jwt";
export { Logger } from "./logger";
export { Mailer } from "./mailer";
export { SMS, Response, LookupResponse } from "./sms";
export { Scheduler, PRIORITY } from "./scheduler";
export { Stripe } from "./stripe";
export { Uploader } from "./uploader";
// Constants
export const HttpStatus = HTTP_STATUS;
export const ErrorCode = ERROR_CODE;
export const LANGUAGE = Language;
// custom error handler
const smsErrorHandle = (error: { code: number, message: string, [key: string]: any }): ExceptionModel => {
switch (error.code) {
case 21211:
case 21614:
return new ExceptionModel(
ErrorCode.RESOURCE.INVALID_PHONE_NUMBER.CODE,
ErrorCode.RESOURCE.INVALID_PHONE_NUMBER.MESSAGE,
false,
HttpStatus.BAD_REQUEST
);
default:
return new ExceptionModel(
ErrorCode.RESOURCE.GENERIC.CODE,
ErrorCode.RESOURCE.GENERIC.MESSAGE,
false,
HttpStatus.BAD_REQUEST
);
}
};
// singleton
export const i18n = new I18N();
export const jwt = new JsonWebToken();
export const config = Config.loadSetting();
export const logger = new Logger(config.log);
export const mailer = new Mailer(config.mailer, logger);
export const sms = new SMS(config.sms, null, smsErrorHandle);
export const firebase = new FirebaseAdmin(config.database ? config.database.firebase : {});
export const fcm = new FCMPush(config.fcm);
export const strip = new Stripe();
export const scheduler = new Scheduler(config.scheduler, logger);
export const uploader = new Uploader(config.storage);
/**
* Created by phuongho on 15/08/17.
*/
import * as jwt from "jsonwebtoken";
export interface BearerObject {
exp: number;
iat: number;
iss: string;
aud: string;
[key: string]: any;
}
export class JsonWebToken {
public static readonly DEFAULT_ISSUER = "Ventuso LLC";
public static readonly DEFAULT_CLIENT = "simulator";
public static readonly DEFAULT_EXPIRE = 365 * 24 * 60 * 60 * 1000; // 1 year
public static readonly DEFAULT_ALGORITHM = "HS512";
private password: string;
private issuer: string;
private defaultExpireTime: number;
private defaultClient: string;
constructor(opts?: any) {
opts = opts != null ? opts : {};
this.password = opts.password != null && opts.password !== "" ? opts.password : JsonWebToken.DEFAULT_ISSUER;
this.issuer = opts.issuer != null && opts.issuer !== "" ? opts.issuer : JsonWebToken.DEFAULT_ISSUER;
this.defaultClient = opts.defaultClient != null && opts.defaultClient !== "" ? opts.defaultClient : JsonWebToken.DEFAULT_CLIENT;
this.defaultExpireTime = opts.defaultExpireTime != null && opts.defaultExpireTime !== "" ? opts.defaultExpireTime : JsonWebToken.DEFAULT_EXPIRE; // 1 year
}
public encode(payload: object, expire: number = this.defaultExpireTime, client = this.defaultClient): string {
if (payload != null) {
let current = Date.now();
let expiredTime = current + this.defaultExpireTime;
return jwt.sign(
// Payload part
payload,
this.password,
{
// algorithm: this.DEFAULT_ALGORITHM,
expiresIn: expiredTime,
issuer: this.issuer,
audience: client,
});
}
return null;
}
public decode(token: string): BearerObject {
return jwt.decode(token, { complete: true }) as BearerObject;
}
public verify(token: string, client = this.defaultClient): any {
return jwt.verify(token, this.password, {
// algorithms: [this.DEFAULT_ALGORITHM],
audience: client,
issuer: this.issuer,
});
}
}
export default JsonWebToken;
/**
* Created by phuongho on 15/08/17.
*/
import {Message} from "./language";
export class EN implements Message {
appName: string = "Test";
}
export default new EN();
/**
* Created by phuongho on 15/08/17.
*/
import * as path from "path";
import * as glob from "glob";
import {EN as Message} from "./en";
export class I18N {
private opts: any;
private map: any;
constructor(opts?: any) {
this.opts = opts != null ? {...opts} : {};
let acceptableLanguages = glob.sync(`${__dirname}/*.js`)
.map((file) => path.basename(file, ".js"))
.filter((language) => language !== "index" && language !== "language");
this.map = acceptableLanguages.reduce((acc, language) => {
acc[language] = require(`./${language}`).default;
return acc;
}, {} as {[language: string]: Message});
}
public messageOf(language: string): Message {
return this.map[language];
}
}
export * from "./language";
export default I18N;
/**
* Created by phuongho on 15/08/17.
*/
export class Language {
public static readonly EN = "en";
}
export interface Message {
appName: string;
}
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import "le_node";
import * as mkdir from "mkdirp";
import * as path from "path";
import * as trace from "stack-trace";
import * as winston from "winston";
export interface Log {
error(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
info(message: string, meta?: any): void;
debug(message: string, meta?: any): void;
}
export class Logger implements Log {
private httpLogger: winston.LoggerInstance;
private processLogger: winston.LoggerInstance;
private logFolder: string;
constructor(opts?: any) {
this.logFolder = ".";
opts = opts || {};
this.init(opts);
}
public getTransportLogger(): winston.LoggerInstance {
return this.httpLogger;
}
public error(message: string, meta?: any): void {
if (meta != null) {
if (meta instanceof Error && meta.stack != null) {
this.processLogger.error(message, { stack: trace.parse(meta) });
} else {
this.processLogger.error(message, meta);
}
} else {
this.processLogger.error(message);
}
}
public warn(message: string, meta?: any): void {
if (meta != null) {
this.processLogger.warn(message, meta);
} else {
this.processLogger.warn(message);
}
}
public info(message: string, meta?: any): void {
if (meta != null) {
this.processLogger.info(message, meta);
} else {
this.processLogger.info(message);
}
}
public debug(message: string, meta?: any): void {
if (meta != null) {
this.processLogger.debug(message, meta);
} else {
this.processLogger.debug(message);
}
}
private createFolder(pathToFolder: string): Promise<boolean> {
if (pathToFolder == null) {
return Promise.resolve(false);
}
return new Promise<boolean>((resolve, reject) => {
mkdir(pathToFolder, err => {
if (err != null) {
reject(err);
} else {
resolve(true);
}
});
});
}
private init(opts: any): void {
this.logFolder = path.join(__dirname, "..", "logs");
if (process.env.NODE_ENV !== "test") {
this.createFolder(this.logFolder)
.then(result => {
if (result) {
this.info("Creating logs folder successful");
} else {
this.warn("Creating logs folder failed");
}
})
.catch(err => {
this.error(err.message, err);
});
}
let console = new winston.transports.Console({
level: "debug",
handleExceptions: true,
timestamp: true,
json: false,
colorize: true,
useConsole: true,
});
let processTransports: winston.TransportInstance[] = [];
if (opts.console != null && process.env.NODE_ENV !== "test") {
let consoleTrans = new winston.transports.Console(opts.console);
processTransports.push(consoleTrans);
}
if (opts.file != null && opts.file.process != null && process.env.NODE_ENV !== "test") {
let conf: any = opts.file.process;
conf.filename = `${this.logFolder}${path.sep}${opts.file.process.name}`;
let fileTrans = new winston.transports.File(conf);
processTransports.push(fileTrans);
}
this.processLogger = new winston.Logger({
transports: processTransports,
exitOnError: opts.exitOnError != null ? opts.exitOnError : false,
});
if (opts.logentries != null && opts.logentries.transportToken != null && opts.logentries.transportToken !== "" && process.env.NODE_ENV !== "testing") {
this.processLogger.add(winston.transports["Logentries"], {
token: opts.logentries.processToken,
json: true,
});
}
let httpTransports: winston.TransportInstance[] = [];
if (opts.console != null && process.env.NODE_ENV !== "test") {
httpTransports.push(console);
}
if (opts.file != null && opts.file.transport != null && process.env.NODE_ENV !== "test") {
let conf: any = opts.file.transport;
conf.filename = `${this.logFolder}${path.sep}${opts.file.transport.name}`;
let fileHttpTrans = new winston.transports.File(conf);
httpTransports.push(fileHttpTrans);
}
this.httpLogger = new winston.Logger({
transports: httpTransports,
exitOnError: false,
});
if (opts.logentries != null && opts.logentries.transportToken != null && opts.logentries.transportToken !== "" && process.env.NODE_ENV !== "test") {
this.httpLogger.add(winston.transports["Logentries"], {
token: opts.logentries.transportToken,
json: true,
});
}
}
}
export default Logger;
/**
* Created by phuongho on 15/08/17.
*/
import * as MailGun from "mailgun-js";
import * as Mailgen from "mailgen";
import * as Promise from "bluebird";
import * as _ from "lodash";
import * as fs from "fs";
import * as htmlToText from "html-to-text";
import * as path from "path";
import { EMAIL_TEMPLATE } from "./constants";
import { UserModel } from "../models";
import { Utils } from "./utils";
let templatesDir = path.resolve(__dirname, "..", "resources/email_templates");
interface MailerConf {
generator: {
name: string;
link: string;
logo: string;
contactEmail: string;
};
mailGun: {
apiKey: string;
domain: string;
sender: string;
};
}
interface Log {
error(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
info(message: string, meta?: any): void;
debug(message: string, meta?: any): void;
}
export class Mailer {
private generator: Mailgen;
private client: MailGun;
private opts: MailerConf;
constructor(opts: any, private logger?: Log) {
this.logger = logger || {
error: (message: string, meta?: any): void => { },
warn: (message: string, meta?: any): void => { },
info: (message: string, meta?: any): void => { },
debug: (message: string, meta?: any): void => { },
};
let defaultConf = {
generator: {
name: "ventuso",
link: "ventuso",
logo: "ventuso",
iOSAppUrl: "",
androidAppUrl: "",
privacyPolicyUrl: "",
contactEmail: "support@ventuso.net"
},
mailGun: {
apiKey: "ventuso",
domain: "ventuso.net",
sender: "support@ventuso.net"
},
};
this.opts = _.defaultsDeep(opts, defaultConf) as MailerConf;
this.generator = new Mailgen({
theme: "default",
product: {
name: this.opts.generator.name,
link: this.opts.generator.link,
logo: this.opts.generator.logo,
},
});
this.client = MailGun({ apiKey: this.opts.mailGun.apiKey, domain: this.opts.mailGun.domain });
}
/**
* @param jsonContent
* @returns {any}
*/
public generateHtml(jsonContent) {
if (jsonContent == null || jsonContent === "") {
throw new Error("Invalid JSON");
}
return this.generator.generate(jsonContent);
}
/**
* @param options
* @returns {Bluebird}
*/
public generateCustomHtml(options: any) {
let defaultData = this.opts.generator;
let opts = Utils.cleanNull(options.data);
let data = _.merge(defaultData, opts);
_.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
return new Promise(function (resolve, reject) {
fs.readFile(templatesDir + "/" + options.template + ".html", { encoding: "utf8" }, function (err, fileContent) {
if (err) {
reject(err);
}
try {
// insert user-specific data into the email
let template = _.template(fileContent);
let htmlContent = template(data);
// generate a plain-text version of the same email
let textContent = htmlToText.fromString(htmlContent);
resolve({
html: htmlContent,
text: textContent
});
}
catch (error) {
reject(error);
}
});
});
}
/**
* @param toEmail
* @param title
* @param jsonContent
* @returns {any}
*/
public send(toEmail: string, title: string, jsonContent: any): Promise<any> {
if (jsonContent == null || jsonContent === "") {
return Promise.reject(new Error("Invalid JSON"));
}
let message = {
from: this.opts.mailGun.sender,
to: toEmail,
subject: title,
html: this.generator.generate(jsonContent),
};
return new Promise((resolve, reject) => {
this.client.messages().send(message, (err, body) => {
if (err != null) {
reject(err);
} else {
resolve(body);
}
});
});
}
/**
*
* @param toEmail
* @param title
* @param jsonContent
* @returns {any}
*/
public sendCustomHtml(toEmail: string, title: string, options: any): Promise<any> {
return this.generateCustomHtml(options)
.then((res: any) => {
let message = {
from: options.from ? options.from : this.opts.mailGun.sender,
to: toEmail,
subject: title,
html: res.html,
};
return new Promise((resolve, reject) => {
this.client.messages().send(message, (err, body) => {
if (err != null) {
reject(err);
} else {
resolve(body);
}
});
});
})
.catch(error => {
this.logger.error(`Send email to ${toEmail} with error:` + error.message, error);
});
}
/**
* @param toEmail
* @param receiverName
* @param resetLink
* @returns {Promise<any>}
*/
// public resetPassword(toEmail, receiverName, resetLink) {
// let message = {
// body: {
// name: receiverName,
// intro: "You have received this email because a password reset request for your account was received.",
// action: {
// instructions: "Click the button below to reset your password:",
// button: {
// color: "red",
// text: "Reset your password",
// link: resetLink,
// },
// },
// outro: "If you did not request a password reset, no further action is required on your part.",
// },
// };
//
// return this.send(toEmail, "Message from iCondo", message);
// }
/**
* @param toEmail
* @param receiverName
* @param password
* @returns {Promise<any>}
*/
// public sendNewPassword(toEmail, receiverName, password) {
// let message = {
// body: {
// name: receiverName,
// intro: "Your new password has been created.",
// action: {
// instructions: "Please use this new password to login and change password as soon as possible.",
// button: {
// color: "blue",
// text: password,
// },
// },
// outro: "Need help, or have questions? Just reply to this email, we\"d love to help.",
// },
// };
//
// return this.send(toEmail, "Message from iCondo", message);
// }
/**
* @param email
* @param mobilePhone
* @param pinCode
* @returns {Bluebird<U>}
*/
// public sendPinForTester(email, mobilePhone, pinCode) {
// let message = {
// body: {
// name: "Verify Pin",
// intro: `Your pin of mobile phone:`,
// action: {
// instructions: `Your pin of mobile phone ${mobilePhone}`,
// button: {
// color: "blue",
// text: pinCode,
// },
// },
// outro: "Need help, or have questions? Just reply to this email, we\"d love to help.",
// },
// };
//
// return Promise.resolve()
// .then(() => {
// return this.send(email, "Message from iCondo", message);
// });
//
//
// }
/**
* @param toEmail
* @param intro
* @returns {Promise<any>}
*/
// public sendRequestQuote(toEmail, intro) {
// let message = {
// body: {
// name: "Request Quote",
// intro: "Send mail request quote",
// outro: "Need help, or have questions? Just reply to this email, we\"d love to help.",
// },
// };
//
// return this.send(toEmail, "Message from iCondo", message);
// }
/**
* send reset message
* @param userModel
* @param resetLink
* @returns {Promise<any>}
*/
public sendResetPassword(userModel: UserModel, resetLink): Promise<any> {
return Promise.resolve()
.then(() => {
let obj = {
template: EMAIL_TEMPLATE.RESET_PASSWORD,
data: {
resetLink: resetLink,
}
};
return this.sendCustomHtml(userModel.email, `Reset you password`, obj);
})
.catch(error => {
this.logger.error(`Send mail to ${userModel.email}`, error);
});
}
/**
* send new password
* @param userModel
* @param newPassword
* @returns {Promise<any>}
*/
public sendNewPassword(userModel: UserModel, newPassword): Promise<any> {
return Promise.resolve()
.then(() => {
let obj = {
template: EMAIL_TEMPLATE.NEW_PASSWORD,
data: {
name: userModel.firstName,
newPassword: newPassword,
}
};
return this.sendCustomHtml(userModel.email, `NEW password`, obj);
})
.catch(error => {
this.logger.error(`Send mail to ${userModel.email}`, error);
});
}
}
export default Mailer;
import "reflect-metadata";
import { BookshelfMetadata, BOOKSHELF_METADATA_KEY } from "./bookshelf.metadata";
export function Bookshelf<T>(metadata?: BookshelfMetadata<T> | string): any {
if (metadata instanceof String || typeof metadata === "string") {
return Reflect.metadata(BOOKSHELF_METADATA_KEY, {
name: metadata,
relation: undefined,
clazz: undefined,
ignore: false,
omitEmpty: false,
converter: undefined,
});
} else {
let metadataObj = <BookshelfMetadata<T>>metadata;
return Reflect.metadata(BOOKSHELF_METADATA_KEY, metadataObj);
}
}
import "reflect-metadata";
import { BookshelfConverter, BookshelfMetadata, BOOKSHELF_METADATA_KEY } from "./bookshelf.metadata";
import { Utils } from "./utils";
export class BookshelfMapper {
private static getClazz(target: any, propertyKey: string): any {
return Reflect.getMetadata("design:type", target, propertyKey);
}
private static getBookshelfProperty<T>(target: any, propertyKey: string): BookshelfMetadata<T> {
return Reflect.getMetadata(BOOKSHELF_METADATA_KEY, target, propertyKey);
}
private static serializeProperty(metadata: BookshelfMetadata<any>, prop: any): any {
if (!metadata || metadata.ignore === true) {
return;
}
if (prop == null) {
return;
}
if (metadata.converter) {
return metadata.converter.toBookshelf(prop);
}
if (Utils.isArray(prop)) {
return prop.map((propItem: any) => BookshelfMapper.serialize(propItem));
}
return BookshelfMapper.serialize(prop);
}
static serialize(instance: any): any {
if (!Utils.isType(instance, "object") || Utils.isArray(instance)) {
return instance;
}
let obj: any = {};
Object.keys(instance).forEach((key: string) => {
let metadata = BookshelfMapper.getBookshelfProperty(instance, key);
if (metadata != null && metadata.name != null) {
obj[metadata.name] = BookshelfMapper.serializeProperty(metadata, instance[key]);
}
});
return obj;
}
static deserialize<T>(clazz: { new(): T }, bookshelfModel: any): T {
if ((clazz == null) || (bookshelfModel == null) || (bookshelfModel.get == null)) {
return undefined;
}
let obj = new clazz();
Object.keys(obj).forEach((key) => {
let metadata = BookshelfMapper.getBookshelfProperty(obj, key);
if (metadata != null) {
let clazz = BookshelfMapper.getClazz(obj, key);
if (metadata.name != null) {
let propertyName = metadata.name || key;
let val = bookshelfModel.get(propertyName);
if (val != null) {
if (metadata.converter != null) {
obj[key] = metadata.converter.fromBookshelf(val);
} else {
obj[key] = val;
}
}
}
else if (metadata.relation != null) {
let dto = bookshelfModel.related(metadata.relation);
if (Utils.isArray(dto.models) && dto.models.length) {
let arr = [];
dto.models.forEach(model => {
let temp = BookshelfMapper.deserialize(metadata.clazz, model);
arr.push(temp);
});
obj[key] = arr;
} else {
if (dto.get(dto.idAttribute) != null) {
obj[key] = BookshelfMapper.deserialize(clazz, dto);
}
}
}
}
});
return obj;
}
}
export interface BookshelfConverter<T> {
fromBookshelf(data: any): T;
toBookshelf(data: T): any;
}
export interface BookshelfMetadata<T> {
name?: string;
relation?: string;
omitEmpty?: boolean;
ignore?: boolean;
clazz?: { new(): T };
converter?: BookshelfConverter<any>;
}
export const BOOKSHELF_METADATA_KEY: string = "bookshelf_metadata";
export { JsonConverter } from "./json.metadata";
export { Json } from "./json.decorator";
export { JsonMapper } from "./json.mapper";
export { BookshelfMapper } from "./bookshelf.mapper";
export { Bookshelf } from "./bookshelf.decorator";
export { BookshelfConverter } from "./bookshelf.metadata";
import "reflect-metadata";
import { JsonMetadata, JSON_METADATA_KEY } from "./json.metadata";
export function Json<T>(metadata?: JsonMetadata<T> | string): any {
if (metadata instanceof String || typeof metadata === "string") {
return Reflect.metadata(JSON_METADATA_KEY, {
name: metadata,
clazz: undefined,
omitEmpty: false,
ignore: false,
converter: undefined,
});
} else {
let metadataObj = <JsonMetadata<T>>metadata;
return Reflect.metadata(JSON_METADATA_KEY, metadataObj);
}
}
import "reflect-metadata";
import { JsonConverter, JsonMetadata, JSON_METADATA_KEY } from "./json.metadata";
import { Utils } from "./utils";
export class JsonMapper {
private static getClazz(target: any, propertyKey: string): any {
return Reflect.getMetadata("design:type", target, propertyKey);
}
private static getJsonProperty<T>(target: any, propertyKey: string): JsonMetadata<T> {
return Reflect.getMetadata(JSON_METADATA_KEY, target, propertyKey);
}
private static serializeProperty(metadata: JsonMetadata<any>, prop: any): any {
if (!metadata || metadata.ignore === true) {
return;
}
if (metadata.converter) {
return metadata.converter.toJson(prop);
}
if (!metadata.clazz) {
if (metadata.omitEmpty) {
if (Utils.isArray(prop) && prop.length === 0) {
return;
} else if (Utils.isType(prop, "string") && prop === "") {
return;
} else if (Utils.isType(prop, "object") && prop == null) {
return;
}
}
return prop;
}
if (Utils.isArray(prop)) {
return prop.map((propItem: any) => JsonMapper.serialize(propItem));
}
return JsonMapper.serialize(prop);
}
static serialize(instance: any): any {
if (!Utils.isType(instance, "object")) {
return instance;
}
if (Utils.isArray(instance)) {
let arr = [];
instance.forEach(element => {
arr.push(JsonMapper.serialize(element));
});
return arr;
}
let obj: any = {};
Object.keys(instance).forEach((key: string) => {
let metadata = JsonMapper.getJsonProperty(instance, key);
if (metadata != null && metadata.name != null) {
obj[metadata.name] = JsonMapper.serializeProperty(metadata, instance[key]);
}
});
return obj;
}
static deserialize<T>(clazz: { new (): T }, jsonObject): T {
if (clazz == null || jsonObject == null) {
return;
}
if (Utils.isPrimitive(clazz)) {
return jsonObject;
}
let obj = new clazz();
Object.keys(obj).forEach((key) => {
let metadata = JsonMapper.getJsonProperty(obj, key);
let clazz = JsonMapper.getClazz(obj, key);
if (metadata != null && metadata.name != null) {
let innerJson = jsonObject[metadata.name];
if (Utils.isArray(clazz)) {
if (innerJson != null && Utils.isArray(innerJson)) {
if (metadata.clazz != null && !Utils.isPrimitive(metadata.clazz)) {
obj[key] = innerJson
.map((item) => JsonMapper.deserialize(metadata.clazz, item))
.filter(item => item != null);
} else if (metadata.converter != null) {
obj[key] = innerJson
.map((item) => metadata.converter.fromJson(item))
.filter(item => item != null);
} else {
obj[key] = innerJson
.filter(item => item != null);
}
} else {
obj[key] = [];
}
} else if (innerJson != null && !Utils.isArray(innerJson)) {
if (metadata.converter != null) {
obj[key] = metadata.converter.fromJson(innerJson);
} else if (!Utils.isPrimitive(clazz)) {
obj[key] = JsonMapper.deserialize(clazz, innerJson);
} else {
obj[key] = innerJson;
}
}
}
});
return obj;
}
}
export interface JsonConverter<T> {
fromJson(data: any): T;
toJson(data: T): any;
}
export interface JsonMetadata<T> {
name?: string;
omitEmpty?: boolean;
ignore?: boolean;
clazz?: { new(): T };
converter?: JsonConverter<any>;
}
export const JSON_METADATA_KEY: string = "json_metadata";
export class Utils {
public static isType(val: any, type: "object" | "string"): boolean {
return typeof val === type;
}
public static isPrimitive(obj: any): boolean {
switch (typeof obj) {
case "string":
case "number":
case "boolean":
return true;
}
return !!(obj instanceof String || obj === String ||
obj instanceof Number || obj === Number ||
obj instanceof Boolean || obj === Boolean);
}
public static isArray(object: any): boolean {
if (object === Array) {
return true;
} else if (typeof Array.isArray === "function") {
return Array.isArray(object);
}
else {
return !!(object instanceof Array);
}
}
}
import * as moment from "moment";
import { extendMoment, Range } from "moment-range";
declare module "moment" {
function extendMoment(moment: any): any;
interface Moment {
(inp?: moment.MomentInput, format?: moment.MomentFormatSpecification, strict?: boolean): moment.Moment;
(inp?: moment.MomentInput, format?: moment.MomentFormatSpecification, language?: string, strict?: boolean): moment.Moment;
range(start: Date, end: Date): Range;
range(start: Moment, end: Moment): Range;
range(range: Date[]): Range;
range(range: Moment[]): Range;
range(range: string): Range;
}
interface Range {
by(range: string, hollaback?: (current: Moment) => void, exclusive?: boolean): Date[];
by(range: Range, hollaback?: (current: Moment) => void, exclusive?: boolean): Date[];
}
}
export const MomentRange: moment.Moment = extendMoment(moment);
export default MomentRange;
const waitOn = require("wait-on");
import * as Bluebird from "bluebird";
import * as _ from "lodash";
import * as kue from "kue-scheduler";
import { ClientOpts } from "redis";
import { Queue, Job } from "kue";
import { Utils } from "./utils";
declare module "kue" {
export interface Job extends NodeJS.EventEmitter {
unique(unique: string): Job;
}
export interface Queue extends NodeJS.EventEmitter {
enableExpiryNotifications(): void;
clear(listener: Function): void;
every(time: string, job: Job): void;
schedule(time: string | Date, job: Job): void;
now(job: Job): void;
remove(job: string | Job | Object, listener: Function): void;
restore(listener: Function);
process(type: string, context: WorkerContext, listener: Function): void;
}
export interface WorkerContext extends NodeJS.EventEmitter {
resume(): boolean;
pause(timeout: number, fn: Function): void;
shutdown(timeout: number, fn: Function): void;
}
}
export const PRIORITY = {
LOW: "low",
NORMAL: "normal",
MEDIUM: "medium",
HIGH: "high",
CRITICAL: "critical",
};
interface Log {
error(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
info(message: string, meta?: any): void;
debug(message: string, meta?: any): void;
}
interface ExecutorOptions {
debug: boolean;
prefix: string;
skipConfig: boolean;
restore: boolean;
worker?: boolean;
redis: ClientOpts;
}
export class Scheduler {
private queue: Queue;
private logger: Log;
private opts: ExecutorOptions;
constructor(opts: any = {}, logger?: Log) {
let defaultOpts: ExecutorOptions = {
debug: false,
prefix: "dev",
skipConfig: false,
redis: {
port: 6379,
host: "127.0.0.1",
db: "0",
},
restore: true,
};
this.logger = logger || {
error: (message: string, meta?: any): void => { },
warn: (message: string, meta?: any): void => { },
info: (message: string, meta?: any): void => { },
debug: (message: string, meta?: any): void => { },
};
this.opts = _.defaultsDeep(opts, defaultOpts) as ExecutorOptions;
this.opts.worker = false;
}
public initWithWaiting(): Bluebird<boolean> {
this.logger.info("Wait for worker's master");
if (process.env.NODE_ENV === "test") {
return Bluebird.resolve(true);
}
let isComplete = false;
return Utils.PromiseLoop(
() => {
return isComplete === true;
},
() => {
return new Bluebird((resolve, reject) => {
waitOn({
resources: [`tcp:${this.opts.redis.host}:${this.opts.redis.port}`]
}, (err) => {
if (err != null) {
reject(err);
} else {
resolve();
}
});
}).then(() => {
return Bluebird.delay(1000);
}).then(() => {
this.queue = kue.createQueue(this.opts);
this.queue.watchStuckJobs(1000);
isComplete = true;
this.logger.info("Worker's master is OK");
}).catch((err) => {
this.logger.info("Connect to Worker's master failed, try again");
this.logger.error(err.message);
isComplete = false;
});
})
.then((object) => {
return isComplete;
});
}
public createJob(script: string, payload: any, priority: string = PRIORITY.NORMAL): Job {
if (this.queue == null) {
return null;
}
return this.queue.createJob(script, payload)
.attempts(3)
.backoff({
delay: 5000,
type: "fixed",
})
.priority(priority);
}
public createUniqueJob(script: string, payload: any, uniqueKey: string, priority: string = PRIORITY.NORMAL): Job {
if (this.queue == null) {
return null;
}
return this.queue.createJob(script, payload)
.attempts(3)
.backoff({
delay: 5000,
type: "fixed",
})
.priority(priority)
.unique(uniqueKey);
}
public scheduleOneShot(job: Job, triggerTime: Date): void {
if (job != null && triggerTime != null && this.queue != null) {
this.queue.schedule(triggerTime, job);
}
}
public scheduleRepeat(job: Job, cron: string) {
if (job != null && cron != null && cron !== "" && this.queue != null) {
this.queue.every(cron, job);
}
}
public immediatelyJob(job: Job) {
if (job != null) {
this.queue.now(job);
}
}
public isDebug(): boolean {
return this.opts.debug;
}
}
export default Scheduler;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as _ from "lodash";
import * as Twilio from "twilio";
export interface SMSOption {
accountSid: string;
area?: string;
authToken: string;
force?: boolean;
sandbox?: boolean;
sendEmail?: boolean;
sender: string;
}
interface Log {
error(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
info(message: string, meta?: any): void;
debug(message: string, meta?: any): void;
}
export interface Exception {
code: number;
status: number;
message: string;
more_info: string;
}
export interface Response {
sid: string;
account_sid: string;
friendly_name: string;
phone_number: string;
date_created: string;
date_updated: string;
uri: string;
}
export interface Carrier {
error_code: number;
type: string;
name: string;
mobile_network_code: string;
mobile_country_code: string;
}
export interface LookupResponse {
url: string;
carrier: Carrier;
national_format: string;
phone_number: string;
country_code: string;
}
export interface ErrorHandle {
(error: Exception): any;
}
export interface SuccessHandle {
(response: Response | LookupResponse): any;
}
declare module "twilio" {
export interface RestClient extends Client {
lookups: Twilio.LookupsClient;
}
}
export class SMS {
private opts: SMSOption;
private sendClient: Twilio.RestClient;
private lookupsClient: Twilio.LookupsClient;
private errorHandle: ErrorHandle;
private successHandle: SuccessHandle;
constructor(opts: any = {}, success?: SuccessHandle, error?: ErrorHandle, private logger?: Log) {
let defaultOpts: SMSOption = {
accountSid: "AC_ventuso",
authToken: "ventuso",
sender: "ventuso",
};
this.opts = _.defaultsDeep(opts, defaultOpts) as SMSOption;
this.sendClient = Twilio(this.opts.accountSid, this.opts.authToken);
this.lookupsClient = this.sendClient.lookups;
this.logger = logger || {
error: (message: string, meta?: any): void => { },
warn: (message: string, meta?: any): void => { },
info: (message: string, meta?: any): void => { },
debug: (message: string, meta?: any): void => { },
};
this.successHandle = success != null ? success : (response: Response | LookupResponse): any => {
return response;
};
this.errorHandle = error != null ? error : (error: Exception): any => {
return error;
};
}
/**
*
* @param phoneNumber
* @param message
* @returns {Promise<T>|Bluebird<R>|Bluebird<R|U>}
*/
public send(area: string, phoneNumber: string, message: string): Promise<Response> {
try {
return new Promise<Response>((resolve, reject) => {
this.sendClient.messages.create({
to: area + phoneNumber,
from: this.opts.sender,
body: message,
}, (err: Exception, message: Response) => {
if (err != null) {
return reject(this.errorHandle(err));
}
return resolve(message);
});
});
} catch (error) {
this.logger.error(error.message, error);
}
}
/**
*
* @param phoneNumber
* @returns {undefined}
*/
public verifyPhoneNumber(area: string, phoneNumber: string): Promise<LookupResponse> {
try {
if (area === "") {
area = this.opts.area;
}
if (this.opts.sandbox === true) {
area = this.opts.area;
}
return new Promise<LookupResponse>((resolve, reject) => {
this.lookupsClient.phoneNumbers(area + phoneNumber).get((err: Exception, phoneNumber: LookupResponse) => {
if (err != null) {
return reject(this.errorHandle(err));
}
return resolve(phoneNumber);
});
});
} catch (error) {
this.logger.error(error.message, error);
}
}
}
export default SMS;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as StripeSDK from "stripe";
import * as _ from "lodash";
import { CURRENCY } from "./constants";
import { CardModel, ExceptionModel } from "../models";
import { ErrorCode, HttpStatus } from "./";
interface GatewayPayment {
merchantId: string;
publicKey: string;
privateKey: string;
}
export class Stripe {
private gatewayConfig: GatewayPayment;
private gateway;
constructor(_gatewayConfig?: GatewayPayment) {
this.gatewayConfig = _gatewayConfig;
let defaultConf = {
publicKey: "pk_test_x5QbX1gpGO1MlUpP02IVBRYr",
privateKey: "sk_test_0CA93NZpcc0j61MTOXNpty2C"
};
this.gatewayConfig = _.defaultsDeep(_gatewayConfig, defaultConf) as GatewayPayment;
this.gateway = StripeSDK(this.gatewayConfig.privateKey);
}
public createCustomer(cardToken?: string): Promise<any> {
let data = {};
if (cardToken) {
data["source"] = cardToken;
}
return new Promise((resolve, reject) => {
this.gateway.customers.create(data, (err, customer) => {
if (err) {
reject(this.handleError(err));
} else {
resolve(customer.id);
}
});
});
}
public findCustomer(customerId: string): Promise<any> {
return new Promise((resolve, reject) => {
this.gateway.customers.retrieve(customerId, (err, result) => {
if (err) {
reject(this.handleError(err));
} else {
resolve(result);
}
});
});
}
public createCard(customerId: string, cardToken: string): Promise<any> {
return new Promise((resolve, reject) => {
this.gateway.customers.createSource(customerId, {
source: cardToken
}, (err, result) => {
if (err) {
reject(this.handleError(err));
} else {
resolve(CardModel.fromStripeCreditCards(result, result.id));
}
});
});
}
public updateCardDefault(customerId: string, cardId: string): Promise<any> {
return new Promise((resolve, reject) => {
this.gateway.customers.update(customerId, {
default_source: cardId
}, (err, result) => {
if (err) {
reject(this.handleError(err));
} else {
resolve(result);
}
});
});
}
public deleteCard(customerId: string, cardId: string): Promise<any> {
return new Promise((resolve, reject) => {
this.gateway.customers.deleteCard(customerId, cardId, (err, result) => {
if (err) {
reject(this.handleError(err));
} else {
resolve(true);
}
});
});
}
public createTransaction(customerId: string, amount: number, currency: string = CURRENCY.SINGAPORE): Promise<any> {
return new Promise((resolve, reject) => {
if (currency === CURRENCY.SINGAPORE) {
amount = amount * 100;
}
this.gateway.charges.create({
amount: amount,
currency: currency,
customer: customerId
}, (err, result) => {
if (err) {
reject(this.handleError(err));
} else {
resolve(result.id);
}
});
});
}
private handleError(err) {
let error = err;
// switch (err.type) {
// case "StripeAuthenticationError":
// error = new ExceptionModel(
// ErrorCode.PAYMENT.STRIPE_KEY_INVALID.CODE,
// ErrorCode.PAYMENT.STRIPE_KEY_INVALID.MESSAGE,
// false,
// HttpStatus.BAD_REQUEST
// );
// break;
// }
return error;
}
}
export default Stripe;
/**
* Created by kiettv on 7/31/16.
*/
import * as aws from "aws-sdk";
import { S3, Credentials } from "aws-sdk";
import * as Upload from "s3-uploader";
import Meta = Upload.Meta;
import image = Upload.image;
import * as fs from "fs";
import * as Promise from "bluebird";
export class Uploader {
private s3Client: S3;
private bucketName: string;
constructor(opts: any) {
// Default setting;
opts.opts = opts.opts || {};
opts.awsBucketName = opts.awsBucketName ? opts.awsBucketName : "";
opts.opts.aws = opts.opts.aws || {};
aws.config.region = opts.opts.aws.region ? opts.opts.aws.region : "us-west-2";
opts.opts.aws.accessKeyId = opts.opts.aws.accessKeyId ? opts.opts.aws.accessKeyId : "";
opts.opts.aws.secretAccessKey = opts.opts.aws.secretAccessKey ? opts.opts.aws.secretAccessKey : "";
aws.config.update({
credentials: new Credentials(opts.opts.aws.accessKeyId, opts.opts.aws.secretAccessKey),
});
this.s3Client = new aws.S3({
params: {
Bucket: opts.awsBucketName,
ACL: opts.opts.aws.acl ? opts.opts.aws.acl : "public-read",
},
});
this.bucketName = opts.awsBucketName;
}
public uploadFile(path: string, name: string): Promise<any> {
let body = fs.createReadStream(path);
// fs.createReadStream(path).pipe(zlib.createGzip());
let params = {
ACL: "public-read",
Bucket: this.bucketName,
Key: `files/${name}`,
Body: body,
};
return new Promise((resolve, reject) => {
return this.s3Client.upload(params)
.send(function (err, data) {
if (err) {
reject(err);
}
else {
resolve(data);
}
});
});
}
}
export default Uploader;
\ No newline at end of file
/**
* Created by phuongho on 15/08/17.
*/
import * as bcrypt from "bcrypt";
import * as momentTz from "moment-timezone";
import * as Bluebird from "bluebird";
import * as _ from "lodash";
import { Moment } from "moment-timezone";
import { ExceptionModel } from "../models";
import { ErrorCode, HttpStatus } from "../libs";
import { MOMENT_DATE_FORMAT, PASSWORD_LENGTH, TIME_ZONE } from "./constants";
export class Utils {
public static PromiseLoop(condition: () => boolean, action: () => Bluebird<any>): Bluebird<any> {
let loop = () => {
if (condition()) {
return;
}
return Bluebird.resolve(action()).then(loop);
};
return Bluebird.resolve().then(loop);
}
public static stringToDate(date: string): Date {
return momentTz.tz(new Date(date), "GMT").toDate();
}
public static millisecondsToDate(time: number): Date {
return momentTz.tz(new Date(time), "GMT").toDate();
}
public static toDate(date: any): Date {
let result = new Date(date);
if (isNaN(result.getTime())) {
result = new Date(parseInt(date));
}
if (isNaN(result.getTime())) {
throw new ExceptionModel(
ErrorCode.RESOURCE.INVALID_DATE_TYPE.CODE,
ErrorCode.RESOURCE.INVALID_DATE_TYPE.MESSAGE,
false,
HttpStatus.BAD_REQUEST
);
}
return result;
}
public static dateByFormat(date: any, format?: string, timezone?: string): string {
if (!timezone) {
timezone = TIME_ZONE.TIME_ZONE_UTC;
}
if (!format) {
format = MOMENT_DATE_FORMAT.YYYY_MM_DD_H_m;
}
return momentTz.tz(this.toDate(date), timezone).format(format);
}
public static validateEmail(email): boolean {
if (email == null) {
return false;
}
// Regex for validating email.
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
public static randomText(len: number): string {
let set = "0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ";
let setLen = set.length;
let salt = "";
for (let i = 0; i < len; i++) {
let p = Math.floor(Math.random() * setLen);
salt += set[p];
}
return salt;
}
public static randomPassword(len: number): string {
let chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
let randomstring = "";
let charCount = 0;
let numCount = 0;
for (let i = 0; i < len; i++) {
// If random bit is 0, there are less than 3 digits already saved, and there are not already 5 characters saved, generate a numeric value.
if ((Math.floor(Math.random() * 2) === 0) && numCount < 3 || charCount >= 5) {
let rnum = Math.floor(Math.random() * 10);
randomstring += rnum;
numCount += 1;
} else {
// If any of the above criteria fail, go ahead and generate an alpha character from the chars string
let rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum, rnum + 1);
charCount += 1;
}
}
return randomstring;
}
public static randomPin(numberOfCharacter: number): string {
let pin = "";
for (let i = 0; i < numberOfCharacter; i++) {
pin += Math.floor(Math.random() * 10).toString();
}
return pin;
}
public static randomNumber(min: number = Number.MIN_VALUE, max: number = Number.MAX_VALUE): number {
if (min != null && max != null) {
return Math.floor(Math.random() * max + min);
}
return 0;
}
public static compareHash(password: string, hash: string): boolean {
if (password == null || hash == null) {
return false;
}
return bcrypt.compareSync(password, hash);
}
public static hashPassword(password: string): string {
if (password != null) {
return bcrypt.hashSync(password, 10);
}
return "";
}
/**
* Check password strength. Must meet the following criteria:
*
* - Contain at least 6 characters
* - Contain at least 1 number
* - Contain at least 1 lowercase character (a-z)
* - Contain at least 1 uppercase character (A-Z)
* - Contains only 0-9a-zA-Z
* @param password Password to check
* @return {boolean}
*/
public static validatePassword(password): boolean {
if (password == null) {
return false;
}
// let re = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{6,}$/;
// return re.test(password);
return password.length >= PASSWORD_LENGTH;
}
/**
* Round Number
* @returns {string}
* @param num
* @param numberOfDecimalPoint
*/
public static roundNumber(num: number, numberOfDecimalPoint: number = 0): number {
let newNumber = Number(num.toFixed(numberOfDecimalPoint));
return isNaN(newNumber) ? 0 : newNumber;
}
/**
* convert number to string
* @returns {string}
* @param num
*/
public static numberWithCommas(num: number): string {
let parts = num.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
/**
* convert app version to number
* @returns {string}
* @param num
*/
public static versionToNumber(version: string): number {
let parts = version.split(".");
return parseInt(parts[0]) * 100 + parseInt(parts[1]);
}
public static camelCaseString(s: string): string {
let words = s.trim().split(/\s+/);
for (let word of words) {
word = word.replace(/./, word[0].toUpperCase());
}
return words.join(" ");
}
/**
* clean null value
* @param options
* @returns {any}
*/
public static cleanNull(options: any) {
_.each(options, (value, key) => {
if (options[key] === null || options[key] === undefined) {
options[key] = "";
}
});
return options;
}
}
export default Utils;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import * as Promise from "bluebird";
interface OnError {
(meta: number): any;
}
interface OnCheckWhiteList {
(path: string, method: string): boolean;
}
interface OnVerify {
(token: string, deviceId: string): Promise<any>;
}
export const AUTH_CODE = {
INVALID_TOKEN: 1,
INVALID_AUTHORIZATION_HEADER: 2,
VIOLATE_RFC6750: 3,
TOKEN_EXPIRE: 4
};
/**
*
* @param onError Error callback
* @param onCheck URL check callback
* @param onVerify Token verify callback
* @return {express.RequestHandler}
*/
export const authenticate = (onError?: OnError, onCheck?: OnCheckWhiteList, onVerify?: OnVerify): express.RequestHandler => {
const QUERY_KEY = "access_token";
const BODY_KEY = "access_token";
const TRAGEDY_KEY = "Bearer";
const AUTH_HEADER = "authorization";
const DEVICE_HEADER = "device-id";
let errorCallback = onError != null ? onError : (meta: number): any => {
return new Error(meta.toString());
};
//noinspection JSUnusedLocalSymbols
let checkUrlCallback = onCheck != null ? onCheck : (path: string, method: string): boolean => {
return false;
};
//noinspection JSUnusedLocalSymbols
let verifyCallback = onVerify != null ? onVerify : (token: string, deviceId: string): Promise<any> => {
return Promise.resolve(true);
};
return (req: express.Request, res: express.Response, next: express.NextFunction): any => {
return Promise.resolve()
.then(() => {
let token: string;
let error: boolean;
if (req.query && req.query[QUERY_KEY]) {
token = req.query[QUERY_KEY];
}
if (req.body && req.body[BODY_KEY]) {
if (token) {
error = true;
}
token = req.body[BODY_KEY];
}
if (req.header(AUTH_HEADER) != null) {
let parts = req.header(AUTH_HEADER).split(" ");
if (parts.length === 2 && parts[0] === TRAGEDY_KEY) {
if (token) {
error = true;
}
token = parts[1];
}
}
if (error) {
throw errorCallback(AUTH_CODE.VIOLATE_RFC6750);
}
return token;
})
.then(token => {
if ((token == null || token === "") && checkUrlCallback(req.baseUrl, req.method)) {
throw errorCallback(AUTH_CODE.INVALID_AUTHORIZATION_HEADER);
}
return verifyCallback(token, req.header(DEVICE_HEADER));
})
.then((object) => {
if (object != null && object.jwt != null) {
res.locals.session = object.jwt;
next();
} else {
next(errorCallback(AUTH_CODE.INVALID_TOKEN));
}
return true;
})
.catch(error => {
next(errorCallback(error));
});
};
};
export default authenticate;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
export const bodyParseFile = () => {
return (req, res: express.Response, next: express.NextFunction): any => {
req.pipe(req.busboy);
req.body = "";
req.busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
file.on("data", (data => {
req.body += data.toString("utf8");
}));
file.on("end", (data => {
next();
}));
});
};
};
export default bodyParseFile;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { devOpsService } from "../interactors";
import * as Schema from "../data/sql/schema";
import { ExceptionModel } from "../models";
import { Utils, ErrorCode, HttpStatus } from "../libs";
import { HEADERS, PLATFORM } from "../libs/constants";
export const checkVersion = (): express.RequestHandler => {
return (req: express.Request, res: express.Response, next: express.NextFunction): any => {
let platform = req.headers[HEADERS.DEVICE_OS];
let version: number;
if (platform === PLATFORM.IOS || platform === PLATFORM.ANDROID) {
version = parseInt(req.headers[HEADERS.APP_VERSION] as string);
if (isNaN(version)) {
return next(new ExceptionModel(
ErrorCode.PRIVILEGE.INVALID_VERSION.CODE,
ErrorCode.PRIVILEGE.INVALID_VERSION.MESSAGE,
false,
HttpStatus.BAD_REQUEST
));
}
return devOpsService.findAppVersion(platform, version)
.then(app => {
if (!app) {
return next(new ExceptionModel(
ErrorCode.PRIVILEGE.VERSION_NOT_FOUND.CODE,
ErrorCode.PRIVILEGE.VERSION_NOT_FOUND.MESSAGE,
false,
HttpStatus.BAD_REQUEST
));
}
if (app.forceUpdate) {
return next(new ExceptionModel(
ErrorCode.PRIVILEGE.FORCE_UPDATE.CODE,
ErrorCode.PRIVILEGE.FORCE_UPDATE.MESSAGE,
false,
HttpStatus.BAD_REQUEST
));
}
return next();
});
} else {
next();
}
};
};
export default checkVersion;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
interface CorsFunction {
(res: express.Response): void;
}
export const cors = (handle?: CorsFunction): express.RequestHandler => {
return (req: express.Request, res: express.Response, next: express.NextFunction): any => {
res.header("Connection", "close");
res.header("Content-Type", "application/json; charset=utf-8");
// restrict it to the required domain
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,PUT,POST,PATCH,DELETE");
// Set custom headers for CORS
res.header("Access-Control-Allow-Headers", "Content-Type, Accept, Pragma, If-Modified-Since, Cache-Control, Authorization, device-os, app-version");
res.header("Access-Control-Expose-Headers", "Total, Offset, Limit");
if (handle != null) {
handle(res);
}
if (req.method === "OPTIONS") {
res.status(200).end();
} else {
next();
}
};
};
export default cors;
/**
* Created by phuongho on 15/08/17.
*/
import { sessionService, cacheService } from "../interactors";
import { ErrorCode, HttpStatus, jwt as Jwt } from "../libs";
import { HttpCode } from "../libs/http_code";
import { BearerObject } from "../libs/jwt";
import { ExceptionModel, SessionModel } from "../models";
import { AUTH_CODE, authenticate } from "./authentication";
import * as Promise from "bluebird";
import * as express from "express";
export const hasCache = (): express.RequestHandler => {
return (req: express.Request, res: express.Response, next: express.NextFunction): any => {
let response = cacheService.get(req.path);
if (response != null) {
return res.json(response);
}
return next();
};
};
export const hasPrivilege = (roles: string[] = []): express.RequestHandler => {
return (req: express.Request, res: express.Response, next: express.NextFunction): any => {
let session: SessionModel = res.locals.session || SessionModel.empty();
// TODO: KIET - atm check by session's role data, later will move to Redis
let roleId: string = roles.find(item => item === session.roleId);
if (roleId != null) {
next();
} else {
next(new ExceptionModel(
ErrorCode.PRIVILEGE.NOT_ALLOW.CODE,
ErrorCode.PRIVILEGE.NOT_ALLOW.MESSAGE,
false,
HttpStatus.FORBIDDEN,
));
}
};
};
export const isAuthenticated = authenticate(
(meta: number): any => {
let error: ExceptionModel = null;
switch (meta) {
case AUTH_CODE.INVALID_TOKEN:
error = new ExceptionModel(
ErrorCode.AUTHENTICATION.INVALID_TOKEN.CODE,
ErrorCode.AUTHENTICATION.INVALID_TOKEN.MESSAGE,
false,
HttpCode.UNAUTHORIZED
);
break;
case AUTH_CODE.INVALID_AUTHORIZATION_HEADER:
error = new ExceptionModel(
ErrorCode.AUTHENTICATION.INVALID_AUTHORIZATION_HEADER.CODE,
ErrorCode.AUTHENTICATION.INVALID_AUTHORIZATION_HEADER.MESSAGE,
false,
HttpCode.UNAUTHORIZED
);
break;
case AUTH_CODE.VIOLATE_RFC6750:
error = new ExceptionModel(
ErrorCode.AUTHENTICATION.VIOLATE_RFC6750.CODE,
ErrorCode.AUTHENTICATION.VIOLATE_RFC6750.MESSAGE,
false,
HttpCode.UNAUTHORIZED
);
break;
case AUTH_CODE.TOKEN_EXPIRE:
error = new ExceptionModel(
ErrorCode.AUTHENTICATION.TOKEN_EXPIRE.CODE,
ErrorCode.AUTHENTICATION.TOKEN_EXPIRE.MESSAGE,
false,
HttpCode.UNAUTHORIZED
);
break;
default:
error = new ExceptionModel(
ErrorCode.AUTHENTICATION.GENERIC.CODE,
ErrorCode.AUTHENTICATION.GENERIC.MESSAGE,
false,
HttpCode.UNAUTHORIZED
);
}
return error;
},
(path: string, method: string): boolean => {
return false;
},
(token: string, deviceId: string): Promise<any> => {
let jwtObject: BearerObject = null;
return Promise.resolve()
.then(() => {
jwtObject = Jwt.verify(token, deviceId);
let current: number = Date.now();
if (current < jwtObject.exp && Jwt.verify(token, deviceId)) {
return sessionService.verifyToken(jwtObject, token);
} else {
throw AUTH_CODE.TOKEN_EXPIRE;
}
})
.then((object) => {
if (object == null) {
throw AUTH_CODE.INVALID_TOKEN;
}
jwtObject.roleId = object.roleId; // change to reddit
return {
jwt: jwtObject,
};
});
}
);
export * from "./cors";
export * from "./log";
export * from "./not_found";
export * from "./recover";
export * from "./body_parse_file";
export * from "./check_version";
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { ErrorCode, HttpStatus } from "../libs";
import { ExceptionModel } from "../models";
import * as _ from "lodash";
interface LogHandler {
error(message: string, meta?: any): void;
warn(message: string, meta?: any): void;
info(message: string, meta?: any): void;
}
export const httpLogger = (logger?: LogHandler): express.RequestHandler => {
let Logger: LogHandler = logger || {
error: (message: string, meta?: any): void => console.error(message),
warn: (message: string, meta?: any): void => console.warn(message),
info: (message: string, meta?: any): void => console.log(message),
};
return (req: express.Request, res: any, next: express.NextFunction) => {
req["_startTime"] = Date.now();
// Capture end function in Request object to calculate information
let endFunc = res.end;
res.end = (chunk: any, encoding: any) => {
res.responseTime = Date.now() - req["_startTime"];
res.end = endFunc;
res.end(chunk, encoding);
req.url = req.originalUrl || req.url;
let format = `${req.ip} ${req.method} ${req.path} ${res.responseTime}ms ${chunk ? chunk.length : 0}bytes ${res.statusCode} ${res.statusMessage}`;
let meta = {
ip: req.ip,
method: req.method,
path: req.path ? req.path : "",
time: res.responseTime,
size: chunk ? chunk.length : 0,
statusCode: res.statusCode,
headers: req.headers,
body: req.body,
};
switch (true) {
case (req.path === "/api/v1/health"):
break;
case (res.statusCode < 200):
Logger.warn(format, meta);
break;
case (res.statusCode > 199 && res.statusCode < 300):
Logger.info(format, meta);
break;
case (res.statusCode > 299 && res.statusCode < 500):
Logger.warn(format, meta);
break;
default:
Logger.error(format, meta);
}
endFunc = null;
};
next();
};
};
export const httpError = (logger?: any): express.ErrorRequestHandler => {
let Logger = logger || {
error: (message: string, meta?: any): void => console.error(message),
warn: (message: string, meta?: any): void => console.warn(message),
info: (message: string, meta?: any): void => console.log(message),
};
return (error: any, req: express.Request, res: express.Response, next: express.NextFunction): any => {
if (!(_.map(ErrorCode, (o) => o.GENERIC.CODE).find((code) => code === error.code))) {
Logger.warn(error.message, error);
} else {
Logger.error(error.message, error);
}
if (error.httpStatus == null) {
error = ExceptionModel.fromError(
ErrorCode.RESOURCE.GENERIC.CODE,
error,
true,
HttpStatus.INTERNAL_SERVER_ERROR
);
if (process.env.NODE_ENV === "production") {
error.message = ErrorCode.RESOURCE.GENERIC.MESSAGE;
}
}
next(error);
};
};
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { ExceptionModel } from "../models";
import { ErrorCode } from "../libs";
export const notFound = (): express.RequestHandler => {
return (req: express.Request, res: express.Response, next: express.NextFunction): any => {
next(new ExceptionModel(
ErrorCode.RESOURCE.INVALID_URL.CODE,
ErrorCode.RESOURCE.INVALID_URL.MESSAGE,
false,
404,
));
};
};
export default notFound;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
export const privilege = (): express.RequestHandler => {
return (req: express.Request, res: express.Response, next: express.NextFunction): any => {
next();
};
};
export default privilege;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
interface RecoverFunction {
(error: any, res: express.Response): void;
}
export const recover = (handle?: RecoverFunction): express.ErrorRequestHandler => {
let fallback: RecoverFunction = (error: any, res: express.Response): void => {
res.status(500);
res.end();
};
let handler = handle || fallback;
return (error: any, req: express.Request, res: express.Response, next: express.NextFunction): any => {
handler(error, res);
if (!res.finished) {
fallback(error, res);
}
};
};
export default recover;
import * as Schema from "../data/sql/schema";
import * as express from "express";
import * as momentTz from "moment-timezone";
import { APPLICATION_TABLE_SCHEMA } from "./../data/sql/schema";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { PLATFORM } from "./../libs/constants";
export class ApplicationModel extends BaseModel {
@Json("platform")
@Bookshelf(APPLICATION_TABLE_SCHEMA.FIELDS.PLATFORM)
public platform: string = undefined;
@Json("version")
@Bookshelf(APPLICATION_TABLE_SCHEMA.FIELDS.VERSION)
public version: number = undefined;
@Json("isLatest")
@Bookshelf(APPLICATION_TABLE_SCHEMA.FIELDS.IS_LATEST)
public isLatest: boolean = undefined;
@Json("forceUpdate")
@Bookshelf(APPLICATION_TABLE_SCHEMA.FIELDS.FORCE_UPDATE)
public forceUpdate: boolean = undefined;
}
export default ApplicationModel;
import * as express from "express";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { ARTICLES_TABLE_SCHEMA } from "./../data/sql/schema";
export class ArticlesModel extends BaseModel {
@Json("title")
@Bookshelf(ARTICLES_TABLE_SCHEMA.FIELDS.TITLE)
public name: string = undefined;
}
import * as Schema from "../data/sql/schema";
import { ASSIGN_PRESENTATION_TABLE_SCHEMA } from "./../data/sql/schema";
import { BaseModel, JsonBookshelf, JsonString } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { UserModel } from "./user.model";
export class AssignPresentationModel extends BaseModel {
@Json("presentationId")
@Bookshelf(ASSIGN_PRESENTATION_TABLE_SCHEMA.FIELDS.PRESENTATION_ID)
public presentationId: string = undefined;
@Json("country")
@Bookshelf(ASSIGN_PRESENTATION_TABLE_SCHEMA.FIELDS.COUNTRY)
public country: string = undefined;
@Json("state")
@Bookshelf(ASSIGN_PRESENTATION_TABLE_SCHEMA.FIELDS.STATE)
public state: string = undefined;
@Json("province")
@Bookshelf(ASSIGN_PRESENTATION_TABLE_SCHEMA.FIELDS.PROVINCE)
public province: string = undefined;
@Json({ name: "tags" })
@Bookshelf({ name: ASSIGN_PRESENTATION_TABLE_SCHEMA.FIELDS.TAG, converter: JsonBookshelf })
public tags: string[] = undefined;
@Json({ name: "users" })
@Bookshelf({ name: ASSIGN_PRESENTATION_TABLE_SCHEMA.FIELDS.USER, converter: JsonBookshelf })
public users: string[] = undefined;
}
/**
* Created by phuongho on 15/08/17.
*/
import * as _ from "lodash";
import * as moment from "moment";
import * as momentTz from "moment-timezone";
import { Json, JsonConverter, Bookshelf, BookshelfConverter } from "../libs/mapper";
class JsonDateConverter implements JsonConverter<momentTz.Moment> {
public fromJson(data: any): momentTz.Moment {
let date: momentTz.Moment;
if (_.isDate(data)) {
date = momentTz.tz(data, "UTC");
}
else {
date = momentTz.tz(new Date(data), "UTC");
}
return date;
}
public toJson(data: momentTz.Moment): any {
if (data != null && data.isValid()) {
return data.toDate();
}
}
}
export const JsonDate = new JsonDateConverter();
class DateConverter implements BookshelfConverter<momentTz.Moment> {
public fromBookshelf(data: any): momentTz.Moment {
let date: momentTz.Moment;
if (_.isDate(data)) {
date = momentTz.tz(data, "UTC");
}
else {
date = momentTz.tz(new Date(data), "UTC");
}
return date;
}
public toBookshelf(data: momentTz.Moment): any {
if (data != null && data.isValid()) {
return data.toDate();
}
}
}
export const BookshelfDate = new DateConverter();
class JsonStringConverter implements JsonConverter<string> {
public fromJson(data: string): any {
return JSON.parse(data);
}
public toJson(data: any): any {
if (data != null) {
return JSON.stringify(data);
}
}
}
export const JsonString = new JsonStringConverter();
class JsonBookshelfStringConverter implements BookshelfConverter<string> {
public fromBookshelf(data: string): any {
return JSON.parse(data);
}
public toBookshelf(data: any): any {
if (data != null) {
return JSON.stringify(data);
}
}
}
export const JsonBookshelf = new JsonBookshelfStringConverter();
export class BaseModel {
@Json("id")
@Bookshelf("id")
public id: string = undefined;
@Json({ name: "createdDate", converter: JsonDate })
@Bookshelf({ name: "updated_date", converter: BookshelfDate })
public createdDate: momentTz.Moment = undefined;
@Json({ name: "updatedDate", converter: JsonDate })
@Bookshelf({ name: "updated_date", converter: BookshelfDate })
public updatedDate: momentTz.Moment = undefined;
@Bookshelf({ name: "is_deleted"})
public isDeleted: boolean = undefined;
public static hasValue(val: any): boolean {
return !_.isNull(val) && !_.isEmpty(val);
}
/**
* Convert model to JSON
* @param val
* @return {string}
*/
public static toJSON(val: any): string {
return JSON.stringify(val);
}
/**
* Convert model from JSON
* @param val
* @param defaultVal
* @return {T}
*/
public static fromJSON<T>(val: string, defaultVal: T = undefined): T {
try {
let ret = JSON.parse(val);
return ret as T;
}
catch (err) {
return defaultVal;
}
}
/**
* Parse time inverval as Moment object
* @param val
* @param defaultVal
* @return {momentTz.Moment}
*/
public static getTimeInterval(val: any, defaultVal: Date = undefined): momentTz.Moment {
let date: momentTz.Moment;
if (defaultVal != null) {
date = moment(defaultVal, "HH:mm:ss");
}
if (_.isString(val)) {
date = moment(val, "HH:mm:ss");
} else if (_.isDate(val)) {
date = moment(val, "HH:mm:ss");
}
return date;
}
/**
* Parse date as Moment object
* @param val
* @param defaultVal
* @return {momentTz.Moment}
*/
public static getDate(val: any, defaultVal: Date = undefined): momentTz.Moment {
let date: momentTz.Moment;
if (defaultVal != null) {
date = momentTz.tz(defaultVal, "UTC");
}
if (_.isDate(val)) {
date = momentTz.tz(val, "UTC");
}
else if (val != null) {
date = momentTz.tz(new Date(val), "UTC");
} else {
date = val;
}
return date;
}
public static getString(val: any, defaultVal?: string): string {
return (val != null && _.isString(val) && val !== "") ? val : defaultVal != null ? defaultVal : undefined;
}
public static getArrayString(val: string[], defaultVal?: string[]): string[] {
return (val != null && _.isArray(val)) ? val : defaultVal != null ? defaultVal : undefined;
}
public static getBoolean(val: any, defaultVal?: boolean): boolean {
if (val != null) {
if (typeof (val) === "string") {
val = val.toLowerCase();
}
switch (val) {
case true:
case 1:
case "yes":
case "right":
case "true":
case "1":
return true;
default:
return false;
}
}
return defaultVal;
}
public static getNumber(val: any, defaultVal: number = 0): number {
if (val != null) {
let num = Number(val);
return isNaN(val) ? defaultVal : num;
}
return defaultVal;
}
public static filters(object: any, filters: string[] = []): void {
if (object != null) {
filters.forEach(field => {
if (object.hasOwnProperty(field)) {
object[field] = undefined;
}
});
}
}
}
export default BaseModel;
import * as express from "express";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { CATEGORY_TABLE_SCHEMA } from "./../data/sql/schema";
export class CategoryModel extends BaseModel {
@Json("name")
@Bookshelf(CATEGORY_TABLE_SCHEMA.FIELDS.NAME)
public name: string = undefined;
}
/**
* Created by phuongho on 15/08/17.
*/
export class CollectionWrap<T> {
public data: T[] = [];
public total: number = 0;
}
export default CollectionWrap;
import * as express from "express";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
export class CountryModel extends BaseModel {
@Json("name")
public name: string = undefined;
@Json("code")
public code: string = undefined;
}
import { BaseModel } from "./base.model";
import { DEVICE_OS } from "./../libs/constants";
import { DEVICE_TABLE_SCHEMA } from "./../data/sql/schema";
import { DeviceDto, UserDto } from "../data/sql/models";
import { HEADERS, JWT_WEB_TOKEN } from "../libs/constants";
import { Json, Bookshelf } from "../libs/mapper";
import { UserModel } from "./user.model";
export class DeviceModel extends BaseModel {
@Json("userId")
@Bookshelf(DEVICE_TABLE_SCHEMA.FIELDS.USER_ID)
public userId: string = undefined;
@Json("userAgent")
public userAgent: string = undefined;
@Json("deviceId")
@Bookshelf(DEVICE_TABLE_SCHEMA.FIELDS.DEVICE_ID)
public deviceId: string = undefined;
@Json("registrarId")
@Bookshelf(DEVICE_TABLE_SCHEMA.FIELDS.REGISTRAR_ID)
public registrarId: string = undefined;
@Json("deviceOs")
@Bookshelf(DEVICE_TABLE_SCHEMA.FIELDS.DEVICE_OS)
public deviceOs: string = undefined;
@Json("deviceName")
@Bookshelf(DEVICE_TABLE_SCHEMA.FIELDS.DEVICE_NAME)
public deviceName: string = undefined;
@Json("deviceModel")
@Bookshelf(DEVICE_TABLE_SCHEMA.FIELDS.DEVICE_MODEL)
public deviceModel: string = undefined;
@Json("osVersion")
@Bookshelf(DEVICE_TABLE_SCHEMA.FIELDS.OS_VERSION)
public osVersion: string = undefined;
@Json("appVersion")
@Bookshelf(DEVICE_TABLE_SCHEMA.FIELDS.APP_VERSION)
public appVersion: string = undefined;
@Json("buildVersion")
@Bookshelf(DEVICE_TABLE_SCHEMA.FIELDS.BUILD_VERSION)
public buildVersion: string = undefined;
@Json("isSandBox")
@Bookshelf(DEVICE_TABLE_SCHEMA.FIELDS.IS_SANDBOX)
public isSandBox: boolean = undefined;
@Json({ name: "user", clazz: UserModel, omitEmpty: true })
@Bookshelf({ relation: "user", clazz: UserModel })
public user: UserModel = undefined;
/**
* Parse to DeviceModel from header request.
* @param data
* @param userId
* @returns {DeviceModel}
*/
public static fromRequest(data: any, userId: string): DeviceModel {
let model = new DeviceModel();
model.userId = userId;
model.userAgent = BaseModel.getString(data[HEADERS.USER_AGENT]);
model.deviceId = BaseModel.getString(data[HEADERS.DEVICE_ID], JWT_WEB_TOKEN.DEFAULT_CLIENT);
model.registrarId = BaseModel.getString(data[HEADERS.REGISTRAR_ID]);
model.deviceOs = BaseModel.getString(data[HEADERS.DEVICE_OS]);
model.deviceName = BaseModel.getString(data[HEADERS.DEVICE_NAME]);
model.deviceModel = BaseModel.getString(data[HEADERS.DEVICE_MODEL]);
model.osVersion = BaseModel.getString(data[HEADERS.OS_VERSION]);
model.appVersion = BaseModel.getString(data[HEADERS.APP_VERSION]);
model.buildVersion = BaseModel.getString(data[HEADERS.BUILD_VERSION]);
return model;
}
}
export default DeviceModel;
/**
* Created by phuongho on 15/08/17.
*/
import * as trace from "stack-trace";
import { Json, Bookshelf } from "../libs/mapper";
import {ErrorCode, HttpStatus} from "../libs";
export class ExceptionModel implements Error {
@Json("name")
public name: string = undefined;
@Json("stack")
public stack: any = undefined;
@Json("message")
public message: string = undefined;
@Json("code")
public code: number = undefined;
@Json("httpStatus")
public httpStatus: number = undefined;
public static fromError(code: number, error: Error, stack?: boolean, httpStatus?: number): ExceptionModel {
let exception = new ExceptionModel(code, error.message);
exception.name = "ExceptionModel";
exception.message = error.message;
if (stack && error != null) {
exception.stack = trace.parse(error);
}
if (httpStatus != null) {
exception.httpStatus = httpStatus;
} else {
exception.httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
}
return exception;
}
constructor(code: number, message: string, stack?: boolean, httpStatus?: number) {
this.name = "ExceptionModel";
this.code = code;
this.message = message;
if (stack) {
this.stack = trace.parse(<any>new Error());
}
if (httpStatus != null) {
this.httpStatus = httpStatus;
} else {
this.httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
}
}
public toString() {
return `${this.name}: ${this.message}`;
}
}
export default ExceptionModel;
/**
* Created by phuongho on 15/08/17.
*/
export * from "./application.model";
export * from "./assign_presentation.model";
export * from "./base.model";
export * from "./collections";
export * from "./country.model";
export * from "./device.model";
export * from "./exception.model";
export * from "./language.model";
export * from "./media.model";
export * from "./notification.model";
export * from "./package.model";
export * from "./payment.model";
export * from "./presentation.model";
export * from "./role.model";
export * from "./session.model";
export * from "./setting.model";
export * from "./state.model";
export * from "./tag.model";
export * from "./user.model";
export * from "./user_code.model";
export * from "./user_package.model";
export * from "./user_presentation.model";
export * from "./user_tag.model";
export * from "./category.model";
export * from "./articles.model";
import * as express from "express";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { LANGUAGE_TABLE_SCHEMA } from "./../data/sql/schema";
export class LanguageModel extends BaseModel {
@Json("name")
@Bookshelf(LANGUAGE_TABLE_SCHEMA.FIELDS.NAME)
public name: string = undefined;
@Json("code")
@Bookshelf(LANGUAGE_TABLE_SCHEMA.FIELDS.CODE)
public code: string = undefined;
}
/**
* Created by phuongho on 15/08/17.
*/
import * as Schema from "../data/sql/schema";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { MEDIA_TABLE_SCHEMA } from "./../data/sql/schema";
import { MediaDto } from "../data/sql/models";
export class MediaModel extends BaseModel {
@Json("path")
@Bookshelf(MEDIA_TABLE_SCHEMA.FIELDS.PATH)
public path: string = undefined;
@Json("url")
@Bookshelf(MEDIA_TABLE_SCHEMA.FIELDS.URL)
public url: string = undefined;
@Json("signature")
public signature: string = undefined;
public static toResponse(modal: MediaModel): any {
let ret: any = {};
if (modal != null) {
if (BaseModel.hasValue(modal.id)) {
ret.id = modal.id;
}
if (BaseModel.hasValue(modal.createdDate)) {
ret.createdDate = modal.createdDate.toDate();
}
if (BaseModel.hasValue(modal.updatedDate)) {
ret.updatedDate = modal.createdDate.toDate();
}
if (BaseModel.hasValue(modal.path)) {
ret.path = modal.path;
}
if (BaseModel.hasValue(modal.url)) {
ret.url = modal.url;
}
if (BaseModel.hasValue(modal.signature)) {
ret.signature = modal.signature;
}
}
return ret;
}
public static fromDataS3(data: any): MediaModel {
if (data != null) {
let model = new MediaModel();
model.url = BaseModel.getString(data.Location);
model.path = BaseModel.getString(data.Key);
// modal.signature = BaseModel.getString(data.ETag);
return model;
}
return null;
}
}
export default MediaModel;
/**
* Created by phuongho on 15/08/17.
*/
import * as _ from "lodash";
import { Json, Bookshelf } from "../libs/mapper";
import { NOTIFICATION_OPTIONS } from "../libs/constants";
export class NotificationModel {
public iOSDevices: string[] = [];
public androidDevices: string[] = [];
public title: string = "";
public icon: string = NOTIFICATION_OPTIONS.DEFAULT_ICON;
public body: string = "";
public clickAction: string = "";
public contentAvailable: boolean = true;
public sound: string = NOTIFICATION_OPTIONS.DEFAULT_SOUND;
public expire: number = NOTIFICATION_OPTIONS.DEFAULT_EXPIRE;
public priority: string = NOTIFICATION_OPTIONS.PRIORITY.HIGH.VALUE; // android->ios: high -> 10, normal -> 5
public collapse: string = NOTIFICATION_OPTIONS.DEFAULT_COLLAPSE_KEY; // ios: collapseId, android: collapseKey
// Android specifics
public restrictedPackageName?: string;
public delayWhileIdle: boolean = false;
public dryRun: boolean = true;
// iOS specifics
public subtitle?: string;
public badge: number = 1;
// Your data
public data: any = {
fromFCM: true,
type: -1,
itemId: "",
userId: ""
};
public static fromRequest(obj: any): NotificationModel {
let message = new NotificationModel();
if (obj.iOSDevices != null && _.isArray(obj.iOSDevices)) {
obj.iOSDevices.forEach((dev) => {
if (_.isString(dev)) {
message.iOSDevices.push(dev);
}
});
}
if (obj.androidDevices != null && _.isArray(obj.androidDevices)) {
obj.androidDevices.forEach((dev) => {
if (_.isString(dev)) {
message.androidDevices.push(dev);
}
});
}
message.title = obj.title != null && _.isString(obj.title) ? obj.title : NOTIFICATION_OPTIONS.DEFAULT_TITLE;
message.icon = obj.icon != null && _.isString(obj.icon) ? obj.icon : NOTIFICATION_OPTIONS.DEFAULT_ICON;
message.body = obj.body != null && _.isString(obj.body) ? obj.body : NOTIFICATION_OPTIONS.DEFAULT_MESSAGE;
message.sound = obj.sound != null && _.isString(obj.sound) ? obj.sound : NOTIFICATION_OPTIONS.DEFAULT_SOUND;
message.priority = obj.priority != null && _.isString(obj.priority) ? obj.priority : NOTIFICATION_OPTIONS.PRIORITY.HIGH.VALUE;
message.collapse = obj.collapse != null && _.isString(obj.collapse) ? obj.collapse : NOTIFICATION_OPTIONS.DEFAULT_SOUND;
let expire = _.parseInt(obj.expire);
message.expire = isNaN(expire) ? NOTIFICATION_OPTIONS.DEFAULT_EXPIRE : expire;
let badge = _.parseInt(obj.badge);
message.badge = isNaN(badge) ? 1 : badge;
if (obj.payload != null) {
message.data = obj.data;
}
return message;
}
}
export default NotificationModel;
import * as Schema from "../data/sql/schema";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { PACKAGE_TABLE_SCHEMA } from "./../data/sql/schema";
import { PRIORITY } from "./../libs/scheduler";
export class PackageModel extends BaseModel {
@Json("name")
@Bookshelf(PACKAGE_TABLE_SCHEMA.FIELDS.NAME)
public name: string = undefined;
@Json("desc")
@Bookshelf(PACKAGE_TABLE_SCHEMA.FIELDS.DESCRIPTION)
public desc: string = undefined;
@Json("numberAccount")
@Bookshelf(PACKAGE_TABLE_SCHEMA.FIELDS.NUMBER_ACCOUNT)
public numberAccount: number = undefined;
@Json("numberFile")
@Bookshelf(PACKAGE_TABLE_SCHEMA.FIELDS.NUMBER_FILE)
public numberFile: number = undefined;
@Json("price")
@Bookshelf(PACKAGE_TABLE_SCHEMA.FIELDS.PRICE)
public price: number = undefined;
@Json("priority")
@Bookshelf(PACKAGE_TABLE_SCHEMA.FIELDS.PRIORITY)
public priority: number = undefined;
}
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { Json, Bookshelf } from "../libs/mapper";
import {BaseModel} from "./base.model";
import {UserModel} from "./user.model";
export class PaymentModel extends BaseModel {
}
export class CustomerPaymentModel extends BaseModel {
@Json("name")
public name: string = undefined;
@Json("company")
public company: string = undefined;
@Json("email")
public email: string = undefined;
@Json("phone")
public phone: string = undefined;
@Json("fax")
public fax: string = undefined;
@Json("website")
public website: string = undefined;
}
export class CardModel extends BaseModel {
public cardholderName: string;
public cardType: string;
public cvv: string;
public cardNumber: string;
public isDefault: boolean;
public expirationMonth: string;
public expirationYear: string;
public imageUrl: string;
public last4: string; // "last4": "1111",
public token: string;
public maskedNumber: string; // "411111******1111"
public expirationDate: string;
public static fromBraintreeCreditCards(data: any): CardModel {
let ret = new CardModel();
ret.cardholderName = data.cardholderName;
ret.cardType = data.cardType;
ret.cvv = data.cvv;
ret.cardNumber = data.cardNumber;
ret.isDefault = data.default;
ret.expirationMonth = data.expirationMonth;
ret.expirationYear = data.expirationYear;
ret.imageUrl = data.imageUrl;
ret.last4 = data.last4;
ret.maskedNumber = data.maskedNumber;
ret.token = data.token;
ret.expirationDate = data.expirationDate;
return ret;
}
public static fromStripeCreditCards(data: any, cardDefaultId: string): CardModel {
let ret = new CardModel();
ret.cardholderName = data.name;
ret.cardType = data.brand;
ret.cvv = data.cvv;
ret.expirationMonth = data.exp_month;
ret.expirationYear = data.exp_year;
ret.last4 = data.last4;
ret.token = data.id;
ret.isDefault = data.id === cardDefaultId ? true : false;
ret.expirationDate = `${data.exp_month}/${data.exp_year}`;
ret.maskedNumber = `************${data.last4}`;
return ret;
}
}
export default PaymentModel;
import * as Schema from "../data/sql/schema";
import { BaseModel, JsonBookshelf, JsonString } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { PRESENTATION_TABLE_SCHEMA } from "./../data/sql/schema";
import { UserModel } from "./user.model";
export class PresentationModel extends BaseModel {
@Json("userId")
@Bookshelf(PRESENTATION_TABLE_SCHEMA.FIELDS.USER_ID)
public userId: string = undefined;
@Json("userCode")
@Bookshelf(PRESENTATION_TABLE_SCHEMA.FIELDS.USER_CODE)
public userCode: string = undefined;
@Json("title")
@Bookshelf(PRESENTATION_TABLE_SCHEMA.FIELDS.TITLE)
public title: string = undefined;
@Json("desc")
@Bookshelf(PRESENTATION_TABLE_SCHEMA.FIELDS.DESCRIPTION)
public desc: string = undefined;
@Json("imageUrl")
@Bookshelf(PRESENTATION_TABLE_SCHEMA.FIELDS.IMAGE_URL)
public imageUrl: string = undefined;
@Json("fileUrl")
@Bookshelf(PRESENTATION_TABLE_SCHEMA.FIELDS.FILE_URL)
public fileUrl: string = undefined;
@Json("numberPage")
@Bookshelf(PRESENTATION_TABLE_SCHEMA.FIELDS.NUMBER_PAGE)
public numberPage: string = undefined;
@Json({ name: "pageTiming"})
@Bookshelf({ name: PRESENTATION_TABLE_SCHEMA.FIELDS.PAGE_TIMING, converter: JsonBookshelf })
public pageTiming: string[] = undefined;
@Json("language")
@Bookshelf(PRESENTATION_TABLE_SCHEMA.FIELDS.LANGUAGE)
public language: string = undefined;
@Json("priority")
@Bookshelf(PRESENTATION_TABLE_SCHEMA.FIELDS.PRIORITY)
public priority: number = undefined;
@Json({ name: "user", clazz: UserModel, omitEmpty: true })
@Bookshelf({ relation: "user", clazz: UserModel })
public user: UserModel = undefined;
}
import * as Schema from "../data/sql/schema";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { ROLE_TABLE_SCHEMA } from "./../data/sql/schema";
export class RoleModel extends BaseModel {
@Json("name")
@Bookshelf(ROLE_TABLE_SCHEMA.FIELDS.NAME)
public name: string = undefined;
@Json("desc")
@Bookshelf(ROLE_TABLE_SCHEMA.FIELDS.DESCRIPTION)
public desc: string = undefined;
}
import * as Schema from "../data/sql/schema";
import * as momentTz from "moment-timezone";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { JsonDate, BookshelfDate } from "./base.model";
import { SESSION_TABLE_SCHEMA } from "./../data/sql/schema";
import { SessionDto } from "../data/sql/models";
import { UserModel } from "./user.model";
export class SessionModel extends BaseModel {
@Json("userId")
@Bookshelf(SESSION_TABLE_SCHEMA.FIELDS.USER_ID)
public userId: string = undefined;
@Json("token")
@Bookshelf(SESSION_TABLE_SCHEMA.FIELDS.TOKEN)
public token: string = undefined;
@Json("firebaseToken")
public firebaseToken: string = undefined;
@Json("roleId")
public roleId: string = undefined;
@Json({ name: "expire", converter: JsonDate })
@Bookshelf({ name: SESSION_TABLE_SCHEMA.FIELDS.EXPIRE, converter: BookshelfDate })
public expire: momentTz.Moment = undefined;
@Json("hash")
@Bookshelf(SESSION_TABLE_SCHEMA.FIELDS.HASH)
public hash: string = undefined;
@Json({ name: "user", clazz: UserModel, omitEmpty: true })
@Bookshelf({ relation: "user", clazz: UserModel })
public user: UserModel = undefined;
public static empty(): SessionModel {
let ret = new SessionModel();
ret.userId = "";
ret.expire = BaseModel.getDate(new Date());
ret.hash = "";
// ret.roleId = "";
// ret.roleKeyword = "";
ret.token = "";
return ret;
}
public toResponse(): SessionModel {
SessionModel.filters(this, ["isDeleted"]);
return this;
}
}
import * as Schema from "../data/sql/schema";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { SETTING_TABLE_SCHEMA } from "./../data/sql/schema";
export class SettingModel extends BaseModel {
@Json("keyword")
@Bookshelf(SETTING_TABLE_SCHEMA.FIELDS.KEYWORD)
public keyword: string = undefined;
@Json("value")
@Bookshelf(SETTING_TABLE_SCHEMA.FIELDS.VALUE)
public value: string = undefined;
@Json("desc")
@Bookshelf(SETTING_TABLE_SCHEMA.FIELDS.DESC)
public desc: string = undefined;
}
/**
* Created by phuongho on 15/08/17.
*/
import { Json, Bookshelf } from "../libs/mapper";
import { MESSAGE_INFO } from "../libs/constants";
export class StateModel {
@Json("title")
public title: string = undefined;
@Json("code")
public code: number = undefined;
@Json("value")
public value: string = undefined;
@Json("message")
public message: string = undefined;
@Json("totalSuccess")
public totalSuccess: number = undefined;
@Json("totalFail")
public totalFail: number = undefined;
@Json("failIndex")
public failIndex: number[] = undefined;
public static init(code: number, value: string, message: string, title?: string, totalSuccess?: number, totalFail?: number, failIndex?: number[]) {
let model = new StateModel();
model.title = title;
model.code = code;
model.value = value;
model.message = message;
model.totalSuccess = totalSuccess;
model.totalFail = totalFail;
model.failIndex = failIndex;
return model;
}
// State: Create new record successful
public static createSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_CREATE_SUCCESSFUL);
}
// State: Update record successful
public static updateSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_UPDATE_SUCCESSFUL);
}
// // State: Update record unsuccessful
public static updateUnSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_UPDATE_UNSUCCESSFUL);
}
// State: Delete record successful
public static deleteSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_DELETE_SUCCESSFUL);
}
// State: Delete record un successful
public static deleteUnSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_DELETE_UNSUCCESSFUL);
}
// State: Import record successful
public static importSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_IMPORT_SUCCESSFUL);
}
// State: Export record successful
public static exportSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_EXPORT_SUCCESSFUL);
}
// State: Change password successful
public static changePasswordSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_CHANGE_PW_SUCCESSFUL);
}
// State: Apply pin successful
public static applyPinSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_APPLY_PIN_SUCCESSFUL);
}
// State: Reset pin successful
public static resetPinSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_RESET_PIN_SUCCESSFUL);
}
// State: Reset pin successful
public static resetPasswordSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_RESET_PASSWORD_SUCCESSFUL);
}
// State: Update record successful
public static uploadSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_UPLOAD_SUCCESSFUL);
}
public static bulkCreate(totalSuccess: number, totalFail: number, failIndex?: number[]) {
let title = MESSAGE_INFO.MI_IMPORT_SUCCESSFUL;
let message = MESSAGE_INFO.MI_BULK(totalSuccess, totalFail, failIndex);
return this.stateSuccessful(null, message, title, totalSuccess, totalFail, failIndex);
}
// State: like successful
public static likeSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_LIKE_SUCCESSFUL);
}
// State: like successful
public static unLikeSuccessful(value?: string) {
return this.stateSuccessful(value, MESSAGE_INFO.MI_UNLIKE_SUCCESSFUL);
}
// State: Action successful
public static stateSuccessful(value: string, message: string, title?: string, totalSuccess?: number, totalFail?: number, failIndex?: number[]) {
title = title ? title : MESSAGE_INFO.MI_TITLE_MESSAGE;
return this.init(undefined, value, message, title, totalSuccess, totalFail, failIndex);
}
// State: Error
public static stateError(code: number, message: string, title?: string) {
title = title ? title : MESSAGE_INFO.MI_TITLE_MESSAGE;
return this.init(code, undefined, message, title);
}
}
export default StateModel;
import * as Schema from "../data/sql/schema";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { TAG_TABLE_SCHEMA } from "./../data/sql/schema";
import { UserModel } from "./user.model";
export class TagModel extends BaseModel {
@Json("userId")
@Bookshelf(TAG_TABLE_SCHEMA.FIELDS.USER_ID)
public userId: string = undefined;
@Json("name")
@Bookshelf(TAG_TABLE_SCHEMA.FIELDS.NAME)
public name: string = undefined;
@Json("desc")
@Bookshelf(TAG_TABLE_SCHEMA.FIELDS.DESCRIPTION)
public desc: string = undefined;
@Json({ name: "user", clazz: UserModel, omitEmpty: true })
@Bookshelf({ relation: "user", clazz: UserModel })
public user: UserModel = undefined;
}
import * as Schema from "../data/sql/schema";
import * as express from "express";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { RoleModel } from "./role.model";
import { USER_TABLE_SCHEMA } from "./../data/sql/schema";
import { UserDto, RoleDto } from "../data/sql/models";
import { UserPackageModel } from "./user_package.model";
import { UserTagModel } from "./user_tag.model";
export class UserModel extends BaseModel {
@Json("firstName")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.FIRST_NAME)
public firstName: string = undefined;
@Json("lastName")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.LAST_NAME)
public lastName: string = undefined;
@Json("email")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.EMAIL)
public email: string = undefined;
@Json("phone")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.PHONE_NUMBER)
public phone: string = undefined;
@Json("password")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.PASSWORD)
public password: string = undefined;
@Json("avatarUrl")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.AVATAR_URL)
public avatarUrl: string = undefined;
@Json("roleId")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.ROLE_ID)
public roleId: string = undefined;
@Json("parentId")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.PARENT_ID)
public parentId: string = undefined;
@Json("country")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.COUNTRY)
public country: string = undefined;
@Json("state")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.STATE)
public state: string = undefined;
@Json("province")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.PROVINCE)
public province: string = undefined;
@Json("language")
@Bookshelf(USER_TABLE_SCHEMA.FIELDS.LANGUAGE)
public language: string = undefined;
@Json({ name: "role", clazz: RoleModel, omitEmpty: true })
@Bookshelf({ relation: "role", clazz: RoleModel })
public role: RoleModel = undefined;
@Json({ name: "account", clazz: UserModel, omitEmpty: true })
@Bookshelf({ relation: "account", clazz: UserModel })
public account: UserModel = undefined;
@Json({ name: "userTag", clazz: UserTagModel, omitEmpty: true })
@Bookshelf({ relation: "userTag", clazz: UserTagModel })
public userTag: UserTagModel = undefined;
@Json("tags")
public tags: string[] = undefined;
}
import * as Schema from "../data/sql/schema";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { USER_CODE_TABLE_SCHEMA } from "./../data/sql/schema";
import { UserModel } from "./user.model";
export class UserCodeModel extends BaseModel {
@Json("userId")
@Bookshelf(USER_CODE_TABLE_SCHEMA.FIELDS.USER_ID)
public userId: string = undefined;
@Json("name")
@Bookshelf(USER_CODE_TABLE_SCHEMA.FIELDS.NAME)
public name: string = undefined;
@Json("code")
@Bookshelf(USER_CODE_TABLE_SCHEMA.FIELDS.CODE)
public code: string = undefined;
@Json("isUsed")
@Bookshelf(USER_CODE_TABLE_SCHEMA.FIELDS.IS_USED)
public isUsed: boolean = undefined;
@Json({ name: "user", clazz: UserModel, omitEmpty: true })
@Bookshelf({ relation: "user", clazz: UserModel })
public user: UserModel = undefined;
}
import * as Schema from "../data/sql/schema";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { PRIORITY } from "./../libs/scheduler";
import { PackageModel } from "./package.model";
import { USER_PACKAGE_TABLE_SCHEMA } from "./../data/sql/schema";
import { UserModel } from "./user.model";
export class UserPackageModel extends BaseModel {
@Json("userId")
@Bookshelf(USER_PACKAGE_TABLE_SCHEMA.FIELDS.USER_ID)
public userId: string = undefined;
@Json("packageId")
@Bookshelf(USER_PACKAGE_TABLE_SCHEMA.FIELDS.PACKAGE_ID)
public packageId: string = undefined;
@Json("numberAccount")
@Bookshelf(USER_PACKAGE_TABLE_SCHEMA.FIELDS.NUMBER_ACCOUNT)
public numberAccount: number = undefined;
@Json("numberFile")
@Bookshelf(USER_PACKAGE_TABLE_SCHEMA.FIELDS.NUMBER_FILE)
public numberFile: number = undefined;
@Json("price")
@Bookshelf(USER_PACKAGE_TABLE_SCHEMA.FIELDS.PRICE)
public price: number = undefined;
@Json({ name: "user", clazz: UserModel, omitEmpty: true })
@Bookshelf({ relation: "user", clazz: UserModel })
public user: UserModel = undefined;
@Json({ name: "package", clazz: PackageModel, omitEmpty: true })
@Bookshelf({ relation: "package", clazz: PackageModel })
public package: PackageModel = undefined;
}
import * as Schema from "../data/sql/schema";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { PRIORITY } from "./../libs/scheduler";
import { PresentationModel } from "./presentation.model";
import { USER_PRESENTATION_TABLE_SCHEMA } from "./../data/sql/schema";
import { UserModel } from "./user.model";
export class UserPresentationModel extends BaseModel {
@Json("userId")
@Bookshelf(USER_PRESENTATION_TABLE_SCHEMA.FIELDS.USER_ID)
public userId: string = undefined;
@Json("presentationId")
@Bookshelf(USER_PRESENTATION_TABLE_SCHEMA.FIELDS.PRESENTATION_ID)
public presentationId: string = undefined;
@Json({ name: "user", clazz: UserModel, omitEmpty: true })
@Bookshelf({ relation: "user", clazz: UserModel })
public user: UserModel = undefined;
@Json({ name: "presentation", clazz: PresentationModel, omitEmpty: true })
@Bookshelf({ relation: "presentation", clazz: PresentationModel })
public package: PresentationModel = undefined;
}
import * as Schema from "../data/sql/schema";
import { BaseModel } from "./base.model";
import { Json, Bookshelf } from "../libs/mapper";
import { PRIORITY } from "./../libs/scheduler";
import { PackageModel } from "./package.model";
import { TagModel } from "./tag.model";
import { USER_TAG_TABLE_SCHEMA } from "./../data/sql/schema";
import { UserModel } from "./user.model";
export class UserTagModel extends BaseModel {
@Json("userId")
@Bookshelf(USER_TAG_TABLE_SCHEMA.FIELDS.USER_ID)
public userId: string = undefined;
@Json("tagId")
@Bookshelf(USER_TAG_TABLE_SCHEMA.FIELDS.TAG_ID)
public tagId: string = undefined;
@Json({ name: "user", clazz: UserModel, omitEmpty: true })
@Bookshelf({ relation: "user", clazz: UserModel })
public user: UserModel = undefined;
@Json({ name: "tag", clazz: TagModel, omitEmpty: true })
@Bookshelf({ relation: "tag", clazz: TagModel })
public tag: TagModel = undefined;
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
<style data-premailer="ignore" id="template-styles-head">
table {
border-collapse: collapse;
table-layout: fixed;
}
.bgimage {
table-layout: auto;
}
img {
-ms-interpolation-mode: bicubic;
}
a {
text-decoration: underline;
}
a[x-apple-data-detectors] {
text-decoration: underline !important;
font-size: inherit !important;
font-family: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
color: inherit !important;
}
.editor-text {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</style>
<style type="text/css">
@media only screen and (max-width: 480px) {
table {
border-collapse: collapse;
}
.main-width {
width: 100% !important;
}
.mobile-hidden {
display: none !important;
}
td.OneColumnMobile {
display: block !important;
}
.OneColumnMobile {
width: 100% !important;
}
.column .editor-text {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .editor-image.editor-image-hspace-on td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .editor-button-container {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .editor-social td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .block-margin {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-text {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-image.editor-image-hspace-on td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-button-container {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-social td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .block-margin {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-text {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-image.editor-image-hspace-on td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-button-container {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-social td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .block-margin {
padding-left: 20px !important;
padding-right: 20px !important;
}
.editor-button td > table tr > td {
padding: 0px 0px 0px 0px !important;
}
.editor-button td > table tr > td td {
padding: 9px 15px 10px 15px !important;
}
.layout {
padding: 15px 9px 15px 9px !important;
}
.layout-container-border {
padding: 5px 5px 5px 5px !important;
}
.layout-container {
padding: 0px 0px 0px 0px !important;
}
.editor-image img {
width: auto !important;
margin-left: auto !important;
margin-right: auto !important;
}
.editor-image .image-cell {
padding-bottom: 15px !important;
}
.editor-text {
font-size: 16px !important;
}
.preheader-text {
font-size: 12px !important;
}
.section-headline-text {
font-size: 24px !important;
}
.headline-text {
font-size: 24px !important;
}
.subheadline-text {
font-size: 20px !important;
}
.feature {
padding-top: 0px !important;
padding-bottom: 0px !important;
}
.layout-outer {
padding: 0px 20px !important;
}
.feature-heading-text {
font-size: 20px !important;
}
.feature-text {
font-size: 16px !important;
}
.split {
border-top: 5px solid #FFFFFF;
border-bottom: 5px solid #FFFFFF;
padding: 5px 0px !important;
}
.split-layout-margin {
padding: 0px 20px !important;
}
.article {
padding-top: 0px !important;
padding-bottom: 0px !important;
}
.article-heading-text {
font-size: 20px !important;
}
.article-text {
font-size: 16px !important;
}
.social-text {
font-size: 14px !important;
}
.coupon {
padding: 10px 20px 10px 20px !important;
}
.coupon td.coupon-heading-text {
padding: 15px 10px 15px 10px !important;
}
.coupon td.coupon-heading-text {
font-size: 28px !important;
}
.coupon td.coupon-text {
padding: 10px 10px 10px 10px !important;
}
.coupon td.coupon-text {
font-size: 16px !important;
}
.action-block .editor-text {
padding-left: 0px !important;
padding-right: 0px !important;
}
.action-block .poll-answer {
width: 100% !important;
display: block !important;
}
.action-block .poll-button {
width: 100% !important;
}
.web-content .editor-text {
padding-left: 10px !important;
padding-right: 10px !important;
}
.web-content .editor-text {
padding-left: 10px !important;
padding-right: 10px !important;
}
div.MobileFooter {
font-size: 11px !important;
}
td.FooterMobile {
padding: 0px 10px 0px 10px !important;
}
td.MainCenter {
width: 100% !important;
}
table.MainSide {
display: none !important;
}
img.MainSide {
display: none !important;
}
td.MainSide {
display: none !important;
}
.rsvp .editor-text {
padding-left: 0px !important;
padding-right: 0px !important;
}
.rsvp-button-container {
padding-left: 0px !important;
padding-right: 0px !important;
}
.rsvp-button-inner {
padding-left: 0px !important;
padding-right: 0px !important;
}
.rsvp-inner {
padding-left: 20px !important;
padding-right: 20px !important;
}
td[class="footer-main-width"] {
width: 100% !important;
}
td[class="footer-mobile-hidden"] {
display: none !important;
}
span[class="footer-mobile-hidden"] {
display: none !important;
}
span[class~="footer-column"] {
display: block !important;
}
}
@media only screen and (max-width: 320px) {
.layout {
padding: 0px 0px 0px 0px !important;
}
}
</style>
<script id="preview-js" src="preview-init.min.js"></script>
</head>
<body align="center" class="body" style="-ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; margin: 0px; min-width: 100%; padding: 0px; width: 100%;">
<table border="0" cellpadding="0" cellspacing="0" class="template-body" style="text-align: center;" width="100%">
<tbody>
<tr>
<td class="preheader-container">
<div>
<div id="preheader" style="color: transparent; display: none; font-size: 1px; line-height: 1px; max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden;">
<span data-entity-ref="preheader"></span>
</div>
</div>
</td>
</tr>
<tr>
<td align="center" class="template-shell-container">
<div class="bgcolor" style="background: #FFFFFF;">
<table bgcolor="#FFFFFF" border="0" cellpadding="0" cellspacing="0" class="bgimage" style="background: #FFFFFF;" width="100%">
<tbody>
<tr>
<td align="center">
<table align="center" border="0" cellpadding="0" cellspacing="0" class="main-width" style="width: 630px;" width="630">
<tbody>
<tr>
<td align="center" class="layout" style="padding: 15px 5px;" valign="top">
<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="center" bgcolor="#5BC6CC" class="layout-container-border" style="background: #5BC6CC; padding: 10px;" valign="top">
<table align="center" bgcolor="#5BC6CC" border="0" cellpadding="0" cellspacing="0" style="background: #5BC6CC;" width="100%">
<tbody>
<tr>
<td align="center" bgcolor="#FFFFFF" class="layout-container" style="background: #FFFFFF; padding: 0;" valign="top">
<div class="">
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-image">
<table border="0" cellpadding="0" cellspacing="0" class="editor-image editor-image editor-image-vspace-on" width="100%">
<tbody>
<tr>
<td align="center" style="padding-bottom: 10px; padding-top: 10px;" valign="top">
<div class="publish-container">
<img alt="" border="0" class="" hspace="0" src="https://files.constantcontact.com/8f6715b9601/1bd04896-c365-4c0f-a9d1-6b2bc8e589d2.png" style="display: block; height: auto !important; max-width: 100% !important;" vspace="0" width="596">
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-image">
<table border="0" cellpadding="0" cellspacing="0" class="editor-image editor-image editor-image-vspace-on" width="100%">
<tbody>
<tr>
<td align="center" style="padding-bottom: 10px; padding-top: 10px;" valign="top">
<div class="publish-container">
<img alt="" border="0" class="" hspace="0" src="https://files.constantcontact.com/8f6715b9601/3371980a-d8c6-4079-9c1c-b88dd033e6fa.png" style="display: block; height: auto !important; max-width: 100% !important;" vspace="0" width="600">
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-divider">
<table border="0" cellpadding="0" cellspacing="0" class="editor-divider" width="100%">
<tbody>
<tr>
<td align="center" class="" valign="top">
<table class="galileo-ap-content-editor" style="cursor: default;" width="100%">
<tbody>
<tr>
<td align="center" class="divider-base divider-solid" style="padding: 9px 0;" valign="top" width="100%">
<table align="center" border="0" cellpadding="0" cellspacing="0" style="height: 1px; width: 94%;">
<tbody>
<tr>
<td align="center" bgcolor="#5BC6CC" height="1" style="background: #5BC6CC; border-bottom-style: none; height: 1px; line-height: 1px; padding-bottom: 0px;">
<div>
<img alt="" border="0" height="1" hspace="0" src="https://imgssl.constantcontact.com/letters/images/1101116784221/S.gif" style="display: block; height: 1px; width: 5px;" vspace="0" width="5">
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="spacer OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-spacer">
<table border="0" cellpadding="0" cellspacing="0" class="editor-spacer" width="100%">
<tbody>
<tr>
<td align="center" class="spacer-container" valign="top">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="center" class="spacer-base" style="height: 1px; line-height: 1px; padding-bottom: 10px;" valign="top" width="100%">
<div><img alt="" border="0" height="1" hspace="0" src="https://imgssl.constantcontact.com/letters/images/sys/S.gif" style="display: block; height: 1px; width: 5px;" vspace="0" width="5">
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="article OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-heading-text" style="color: #5BC6CC; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 18px; font-weight: bold; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div>
<div>Your password information
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-text" style="color: #1f1f1f; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div style=";">
<div><span style="color: rgb(153, 153, 153); font-size: 20px; font-weight: bold;"></span>
</div>
<div>Thanks for contacting us.&nbsp;
</div>
<div>
<br>
</div>
<div>Please follow the directions below to reset your password.
</div>
<div>
<br>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-button">
<table border="0" cellpadding="0" cellspacing="0" class="editor-button" style="width: 100%;" width="100%">
<tbody>
<tr>
<td class="editor-button-container editor-button-container " style="color: #FFFFFF; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; font-weight: bold; padding: 10px 20px; text-decoration: none;">
<table class="galileo-ap-content-editor" style="width: 100%;">
<tbody>
<tr>
<td align="left" class="MainTextFullWidthTD" style="color: #FFFFFF; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; font-weight: bold; padding: 0px; text-decoration: none;" valign="top">
<table bgcolor="#5BC6CC" border="0" cellpadding="0" cellspacing="0" style="background: #5BC6CC; border-radius: 10px; border-spacing: 0; border: none; moz-border-radius: 10px; padding: 0; width: initial;">
<tbody>
<tr>
<td align="center" class="MainTextFullWidthTD" style="color: #FFFFFF; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; font-weight: bold; padding: 9px 15px 10px; text-decoration: none;" valign="top">
<div>
<div class="MainTextFullWidth">
<a href="{{resetLink}}" style="color: #FFFFFF; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; font-weight: bold; text-decoration: none;" target="_blank">Reset Your Password</a>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="article OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-text" style="color: #1f1f1f; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div style=";">
<div><span style="color: rgb(153, 153, 153); font-size: 20px; font-weight: bold;"></span>
</div>
<div>
<br>
</div>
<div>Warmest regard,
</div>
<div>
<br>
</div>
<div>iCondo Team
</div>
<div>
<br>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-divider">
<table border="0" cellpadding="0" cellspacing="0" class="editor-divider" width="100%">
<tbody>
<tr>
<td align="center" class="" valign="top">
<table class="galileo-ap-content-editor" style="cursor: default;" width="100%">
<tbody>
<tr>
<td align="center" class="divider-base divider-solid" style="padding: 9px 0;" valign="top" width="100%">
<table align="center" border="0" cellpadding="0" cellspacing="0" style="height: 1px; width: 94%;">
<tbody>
<tr>
<td align="center" bgcolor="#5BC6CC" height="1" style="background: #5BC6CC; border-bottom-style: none; height: 1px; line-height: 1px; padding-bottom: 0px;">
<div>
<img alt="" border="0" height="1" hspace="0" src="https://imgssl.constantcontact.com/letters/images/1101116784221/S.gif" style="display: block; height: 1px; width: 5px;" vspace="0" width="5">
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="article OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-text" style="color: #1f1f1f; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div style=";">
<div align="center" style="text-align: center;">
<div style=";">
<span style="font-size: 10px;">Copyright iCondo. All Rights Reserved.</span>
</div>
<div>
<div>
<p>
<span style="font-size: 10px;">We take your privacy very seriously, click to view our&nbsp;</span><span style="font-size: 10px;"><span
style="font-size: 10px;"><span
style="color: #5BC6CC;">privacy policy</span><span style="font-size: 10px;">.</span></span>
</span>
</p>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
<style data-premailer="ignore" id="template-styles-head">
table {
border-collapse: collapse;
table-layout: fixed;
}
.bgimage {
table-layout: auto;
}
img {
-ms-interpolation-mode: bicubic;
}
a {
text-decoration: underline;
}
a[x-apple-data-detectors] {
text-decoration: underline !important;
font-size: inherit !important;
font-family: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
color: inherit !important;
}
.editor-text {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</style>
<style type="text/css">
@media only screen and (max-width: 480px) {
table {
border-collapse: collapse;
}
.main-width {
width: 100% !important;
}
.mobile-hidden {
display: none !important;
}
td.OneColumnMobile {
display: block !important;
}
.OneColumnMobile {
width: 100% !important;
}
.column .editor-text {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .editor-image.editor-image-hspace-on td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .editor-button-container {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .editor-social td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .block-margin {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-text {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-image.editor-image-hspace-on td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-button-container {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-social td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .block-margin {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-text {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-image.editor-image-hspace-on td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-button-container {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-social td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .block-margin {
padding-left: 20px !important;
padding-right: 20px !important;
}
.editor-button td > table tr > td {
padding: 0px 0px 0px 0px !important;
}
.editor-button td > table tr > td td {
padding: 9px 15px 10px 15px !important;
}
.layout {
padding: 15px 9px 15px 9px !important;
}
.layout-container-border {
padding: 5px 5px 5px 5px !important;
}
.layout-container {
padding: 0px 0px 0px 0px !important;
}
.editor-image img {
width: auto !important;
margin-left: auto !important;
margin-right: auto !important;
}
.editor-image .image-cell {
padding-bottom: 15px !important;
}
.editor-text {
font-size: 16px !important;
}
.preheader-text {
font-size: 12px !important;
}
.section-headline-text {
font-size: 24px !important;
}
.headline-text {
font-size: 24px !important;
}
.subheadline-text {
font-size: 20px !important;
}
.feature {
padding-top: 0px !important;
padding-bottom: 0px !important;
}
.layout-outer {
padding: 0px 20px !important;
}
.feature-heading-text {
font-size: 20px !important;
}
.feature-text {
font-size: 16px !important;
}
.split {
border-top: 5px solid #FFFFFF;
border-bottom: 5px solid #FFFFFF;
padding: 5px 0px !important;
}
.split-layout-margin {
padding: 0px 20px !important;
}
.article {
padding-top: 0px !important;
padding-bottom: 0px !important;
}
.article-heading-text {
font-size: 20px !important;
}
.article-text {
font-size: 16px !important;
}
.social-text {
font-size: 14px !important;
}
.coupon {
padding: 10px 20px 10px 20px !important;
}
.coupon td.coupon-heading-text {
padding: 15px 10px 15px 10px !important;
}
.coupon td.coupon-heading-text {
font-size: 28px !important;
}
.coupon td.coupon-text {
padding: 10px 10px 10px 10px !important;
}
.coupon td.coupon-text {
font-size: 16px !important;
}
.action-block .editor-text {
padding-left: 0px !important;
padding-right: 0px !important;
}
.action-block .poll-answer {
width: 100% !important;
display: block !important;
}
.action-block .poll-button {
width: 100% !important;
}
.web-content .editor-text {
padding-left: 10px !important;
padding-right: 10px !important;
}
.web-content .editor-text {
padding-left: 10px !important;
padding-right: 10px !important;
}
div.MobileFooter {
font-size: 11px !important;
}
td.FooterMobile {
padding: 0px 10px 0px 10px !important;
}
td.MainCenter {
width: 100% !important;
}
table.MainSide {
display: none !important;
}
img.MainSide {
display: none !important;
}
td.MainSide {
display: none !important;
}
.rsvp .editor-text {
padding-left: 0px !important;
padding-right: 0px !important;
}
.rsvp-button-container {
padding-left: 0px !important;
padding-right: 0px !important;
}
.rsvp-button-inner {
padding-left: 0px !important;
padding-right: 0px !important;
}
.rsvp-inner {
padding-left: 20px !important;
padding-right: 20px !important;
}
td[class="footer-main-width"] {
width: 100% !important;
}
td[class="footer-mobile-hidden"] {
display: none !important;
}
span[class="footer-mobile-hidden"] {
display: none !important;
}
span[class~="footer-column"] {
display: block !important;
}
}
@media only screen and (max-width: 320px) {
.layout {
padding: 0px 0px 0px 0px !important;
}
}
</style>
<script id="preview-js" src="preview-init.min.js"></script>
</head>
<body align="center" class="body" style="-ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; margin: 0px; min-width: 100%; padding: 0px; width: 100%;">
<table border="0" cellpadding="0" cellspacing="0" class="template-body" style="text-align: center;" width="100%">
<tbody>
<tr>
<td class="preheader-container">
<div>
<div id="preheader" style="color: transparent; display: none; font-size: 1px; line-height: 1px; max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden;">
<span data-entity-ref="preheader"></span>
</div>
</div>
</td>
</tr>
<tr>
<td align="center" class="template-shell-container">
<div class="bgcolor" style="background: #FFFFFF;">
<table bgcolor="#FFFFFF" border="0" cellpadding="0" cellspacing="0" class="bgimage" style="background: #FFFFFF;" width="100%">
<tbody>
<tr>
<td align="center">
<table align="center" border="0" cellpadding="0" cellspacing="0" class="main-width" style="width: 630px;" width="630">
<tbody>
<tr>
<td align="center" class="layout" style="padding: 15px 5px;" valign="top">
<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="center" bgcolor="#5BC6CC" class="layout-container-border" style="background: #5BC6CC; padding: 10px;" valign="top">
<table align="center" bgcolor="#5BC6CC" border="0" cellpadding="0" cellspacing="0" style="background: #5BC6CC;" width="100%">
<tbody>
<tr>
<td align="center" bgcolor="#FFFFFF" class="layout-container" style="background: #FFFFFF; padding: 0;" valign="top">
<div class="">
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-image">
<table border="0" cellpadding="0" cellspacing="0" class="editor-image editor-image editor-image-vspace-on" width="100%">
<tbody>
<tr>
<td align="center" style="padding-bottom: 10px; padding-top: 10px;" valign="top">
<div class="publish-container">
<img alt="" border="0" class="" hspace="0" src="https://files.constantcontact.com/8f6715b9601/1bd04896-c365-4c0f-a9d1-6b2bc8e589d2.png" style="display: block; height: auto !important; max-width: 100% !important;" vspace="0" width="596">
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-image">
<table border="0" cellpadding="0" cellspacing="0" class="editor-image editor-image editor-image-vspace-on" width="100%">
<tbody>
<tr>
<td align="center" style="padding-bottom: 10px; padding-top: 10px;" valign="top">
<div class="publish-container">
<img alt="" border="0" class="" hspace="0" src="https://files.constantcontact.com/8f6715b9601/3371980a-d8c6-4079-9c1c-b88dd033e6fa.png" style="display: block; height: auto !important; max-width: 100% !important;" vspace="0" width="600">
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-divider">
<table border="0" cellpadding="0" cellspacing="0" class="editor-divider" width="100%">
<tbody>
<tr>
<td align="center" class="" valign="top">
<table class="galileo-ap-content-editor" style="cursor: default;" width="100%">
<tbody>
<tr>
<td align="center" class="divider-base divider-solid" style="padding: 9px 0;" valign="top" width="100%">
<table align="center" border="0" cellpadding="0" cellspacing="0" style="height: 1px; width: 94%;">
<tbody>
<tr>
<td align="center" bgcolor="#5BC6CC" height="1" style="background: #5BC6CC; border-bottom-style: none; height: 1px; line-height: 1px; padding-bottom: 0px;">
<div>
<img alt="" border="0" height="1" hspace="0" src="https://imgssl.constantcontact.com/letters/images/1101116784221/S.gif" style="display: block; height: 1px; width: 5px;" vspace="0" width="5">
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="spacer OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-spacer">
<table border="0" cellpadding="0" cellspacing="0" class="editor-spacer" width="100%">
<tbody>
<tr>
<td align="center" class="spacer-container" valign="top">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="center" class="spacer-base" style="height: 1px; line-height: 1px; padding-bottom: 10px;" valign="top" width="100%">
<div><img alt="" border="0" height="1" hspace="0" src="https://imgssl.constantcontact.com/letters/images/sys/S.gif" style="display: block; height: 1px; width: 5px;" vspace="0" width="5">
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="article OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-heading-text" style="color: #5BC6CC; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 18px; font-weight: bold; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div>
<div>Hi {{firstName}}!</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-text" style="color: #1f1f1f; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div style=";">
<div><span style="color: rgb(153, 153, 153); font-size: 20px; font-weight: bold;"></span>
</div>
<div>
<p>Your new password has been created.</p>
<p>Please use this new password to login and change password as soon as possible.</p>
</div>
<div>
<br>
</div>
<div>
<br>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-button">
<table border="0" cellpadding="0" cellspacing="0" class="editor-button" style="width: 100%;" width="100%">
<tbody>
<tr>
<td class="editor-button-container editor-button-container " style="color: #FFFFFF; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; font-weight: bold; padding: 10px 20px; text-decoration: none;">
<table class="galileo-ap-content-editor" style="width: 100%;">
<tbody>
<tr>
<td align="left" class="MainTextFullWidthTD" style="color: #FFFFFF; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; font-weight: bold; padding: 0px; text-decoration: none;" valign="top">
<table bgcolor="#5BC6CC" border="0" cellpadding="0" cellspacing="0" style="background: #5BC6CC; border-radius: 10px; border-spacing: 0; border: none; moz-border-radius: 10px; padding: 0; width: initial;">
<tbody>
<tr>
<td align="center" class="MainTextFullWidthTD" style="color: #FFFFFF; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; font-weight: bold; padding: 9px 15px 10px; text-decoration: none;" valign="top">
<div>
<div class="MainTextFullWidth">
<span style="color: #FFFFFF; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; font-weight: bold; text-decoration: none;" target="_blank">{{newPassword}}</span>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="article OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-text" style="color: #1f1f1f; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div style=";">
<div><span style="color: rgb(153, 153, 153); font-size: 20px; font-weight: bold;"></span>
</div>
<div>
<br>
</div>
<div>Warmest regard,
</div>
<div>
<br>
</div>
<div>iCondo Team
</div>
<div>
<br>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-divider">
<table border="0" cellpadding="0" cellspacing="0" class="editor-divider" width="100%">
<tbody>
<tr>
<td align="center" class="" valign="top">
<table class="galileo-ap-content-editor" style="cursor: default;" width="100%">
<tbody>
<tr>
<td align="center" class="divider-base divider-solid" style="padding: 9px 0;" valign="top" width="100%">
<table align="center" border="0" cellpadding="0" cellspacing="0" style="height: 1px; width: 94%;">
<tbody>
<tr>
<td align="center" bgcolor="#5BC6CC" height="1" style="background: #5BC6CC; border-bottom-style: none; height: 1px; line-height: 1px; padding-bottom: 0px;">
<div>
<img alt="" border="0" height="1" hspace="0" src="https://imgssl.constantcontact.com/letters/images/1101116784221/S.gif" style="display: block; height: 1px; width: 5px;" vspace="0" width="5">
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="article OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-text" style="color: #1f1f1f; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div style=";">
<div align="center" style="text-align: center;">
<div style=";">
<span style="font-size: 10px;">Copyright iCondo. All Rights Reserved.</span>
</div>
<div>
<div>
<p>
<span style="font-size: 10px;">We take your privacy very seriously, click to view our&nbsp;</span><span style="font-size: 10px;"><span
style="font-size: 10px;"><span
style="color: #5BC6CC;">privacy policy</span><span style="font-size: 10px;">.</span></span>
</span>
</p>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
<style data-premailer="ignore" id="template-styles-head">
table {
border-collapse: collapse;
table-layout: fixed;
}
.bgimage {
table-layout: auto;
}
img {
-ms-interpolation-mode: bicubic;
}
a {
text-decoration: underline;
}
a[x-apple-data-detectors] {
text-decoration: underline !important;
font-size: inherit !important;
font-family: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
color: inherit !important;
}
.editor-text {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</style>
<style type="text/css">
@media only screen and (max-width: 480px) {
table {
border-collapse: collapse;
}
.main-width {
width: 100% !important;
}
.mobile-hidden {
display: none !important;
}
td.OneColumnMobile {
display: block !important;
}
.OneColumnMobile {
width: 100% !important;
}
.column .editor-text {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .editor-image.editor-image-hspace-on td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .editor-button-container {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .editor-social td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column .block-margin {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-text {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-image.editor-image-hspace-on td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-button-container {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .editor-social td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-left .block-margin {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-text {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-image.editor-image-hspace-on td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-button-container {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .editor-social td {
padding-left: 20px !important;
padding-right: 20px !important;
}
.column-right .block-margin {
padding-left: 20px !important;
padding-right: 20px !important;
}
.editor-button td > table tr > td {
padding: 0px 0px 0px 0px !important;
}
.editor-button td > table tr > td td {
padding: 9px 15px 10px 15px !important;
}
.layout {
padding: 15px 9px 15px 9px !important;
}
.layout-container-border {
padding: 5px 5px 5px 5px !important;
}
.layout-container {
padding: 0px 0px 0px 0px !important;
}
.editor-image img {
width: auto !important;
margin-left: auto !important;
margin-right: auto !important;
}
.editor-image .image-cell {
padding-bottom: 15px !important;
}
.editor-text {
font-size: 16px !important;
}
.preheader-text {
font-size: 12px !important;
}
.section-headline-text {
font-size: 24px !important;
}
.headline-text {
font-size: 24px !important;
}
.subheadline-text {
font-size: 20px !important;
}
.feature {
padding-top: 0px !important;
padding-bottom: 0px !important;
}
.layout-outer {
padding: 0px 20px !important;
}
.feature-heading-text {
font-size: 20px !important;
}
.feature-text {
font-size: 16px !important;
}
.split {
border-top: 5px solid #FFFFFF;
border-bottom: 5px solid #FFFFFF;
padding: 5px 0px !important;
}
.split-layout-margin {
padding: 0px 20px !important;
}
.article {
padding-top: 0px !important;
padding-bottom: 0px !important;
}
.article-heading-text {
font-size: 20px !important;
}
.article-text {
font-size: 16px !important;
}
.social-text {
font-size: 14px !important;
}
.coupon {
padding: 10px 20px 10px 20px !important;
}
.coupon td.coupon-heading-text {
padding: 15px 10px 15px 10px !important;
}
.coupon td.coupon-heading-text {
font-size: 28px !important;
}
.coupon td.coupon-text {
padding: 10px 10px 10px 10px !important;
}
.coupon td.coupon-text {
font-size: 16px !important;
}
.action-block .editor-text {
padding-left: 0px !important;
padding-right: 0px !important;
}
.action-block .poll-answer {
width: 100% !important;
display: block !important;
}
.action-block .poll-button {
width: 100% !important;
}
.web-content .editor-text {
padding-left: 10px !important;
padding-right: 10px !important;
}
.web-content .editor-text {
padding-left: 10px !important;
padding-right: 10px !important;
}
div.MobileFooter {
font-size: 11px !important;
}
td.FooterMobile {
padding: 0px 10px 0px 10px !important;
}
td.MainCenter {
width: 100% !important;
}
table.MainSide {
display: none !important;
}
img.MainSide {
display: none !important;
}
td.MainSide {
display: none !important;
}
.rsvp .editor-text {
padding-left: 0px !important;
padding-right: 0px !important;
}
.rsvp-button-container {
padding-left: 0px !important;
padding-right: 0px !important;
}
.rsvp-button-inner {
padding-left: 0px !important;
padding-right: 0px !important;
}
.rsvp-inner {
padding-left: 20px !important;
padding-right: 20px !important;
}
td[class="footer-main-width"] {
width: 100% !important;
}
td[class="footer-mobile-hidden"] {
display: none !important;
}
span[class="footer-mobile-hidden"] {
display: none !important;
}
span[class~="footer-column"] {
display: block !important;
}
}
@media only screen and (max-width: 320px) {
.layout {
padding: 0px 0px 0px 0px !important;
}
}
</style>
<script id="preview-js" src="preview-init.min.js"></script>
</head>
<body align="center" class="body" style="-ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; margin: 0px; min-width: 100%; padding: 0px; width: 100%;">
<table border="0" cellpadding="0" cellspacing="0" class="template-body" style="text-align: center;" width="100%">
<tbody>
<tr>
<td class="preheader-container">
<div>
<div id="preheader" style="color: transparent; display: none; font-size: 1px; line-height: 1px; max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden;">
<span data-entity-ref="preheader"></span>
</div>
</div>
</td>
</tr>
<tr>
<td align="center" class="template-shell-container">
<div class="bgcolor" style="background: #FFFFFF;">
<table bgcolor="#FFFFFF" border="0" cellpadding="0" cellspacing="0" class="bgimage" style="background: #FFFFFF;" width="100%">
<tbody>
<tr>
<td align="center">
<table align="center" border="0" cellpadding="0" cellspacing="0" class="main-width" style="width: 630px;" width="630">
<tbody>
<tr>
<td align="center" class="layout" style="padding: 15px 5px;" valign="top">
<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="center" bgcolor="#5BC6CC" class="layout-container-border" style="background: #5BC6CC; padding: 10px;" valign="top">
<table align="center" bgcolor="#5BC6CC" border="0" cellpadding="0" cellspacing="0" style="background: #5BC6CC;" width="100%">
<tbody>
<tr>
<td align="center" bgcolor="#FFFFFF" class="layout-container" style="background: #FFFFFF; padding: 0;" valign="top">
<div class="">
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-image">
<table border="0" cellpadding="0" cellspacing="0" class="editor-image editor-image editor-image-vspace-on" width="100%">
<tbody>
<tr>
<td align="center" style="padding-bottom: 10px; padding-top: 10px;" valign="top">
<div class="publish-container">
<img alt="" border="0" class="" hspace="0" src="https://files.constantcontact.com/8f6715b9601/1bd04896-c365-4c0f-a9d1-6b2bc8e589d2.png" style="display: block; height: auto !important; max-width: 100% !important;" vspace="0" width="596">
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-image">
<table border="0" cellpadding="0" cellspacing="0" class="editor-image editor-image editor-image-vspace-on" width="100%">
<tbody>
<tr>
<td align="center" style="padding-bottom: 10px; padding-top: 10px;" valign="top">
<div class="publish-container">
<img alt="" border="0" class="" hspace="0" src="https://files.constantcontact.com/8f6715b9601/3371980a-d8c6-4079-9c1c-b88dd033e6fa.png" style="display: block; height: auto !important; max-width: 100% !important;" vspace="0" width="600">
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-divider">
<table border="0" cellpadding="0" cellspacing="0" class="editor-divider" width="100%">
<tbody>
<tr>
<td align="center" class="" valign="top">
<table class="galileo-ap-content-editor" style="cursor: default;" width="100%">
<tbody>
<tr>
<td align="center" class="divider-base divider-solid" style="padding: 9px 0;" valign="top" width="100%">
<table align="center" border="0" cellpadding="0" cellspacing="0" style="height: 1px; width: 94%;">
<tbody>
<tr>
<td align="center" bgcolor="#5BC6CC" height="1" style="background: #5BC6CC; border-bottom-style: none; height: 1px; line-height: 1px; padding-bottom: 0px;">
<div>
<img alt="" border="0" height="1" hspace="0" src="https://imgssl.constantcontact.com/letters/images/1101116784221/S.gif" style="display: block; height: 1px; width: 5px;" vspace="0" width="5">
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="spacer OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-spacer">
<table border="0" cellpadding="0" cellspacing="0" class="editor-spacer" width="100%">
<tbody>
<tr>
<td align="center" class="spacer-container" valign="top">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="center" class="spacer-base" style="height: 1px; line-height: 1px; padding-bottom: 10px;" valign="top" width="100%">
<div><img alt="" border="0" height="1" hspace="0" src="https://imgssl.constantcontact.com/letters/images/sys/S.gif" style="display: block; height: 1px; width: 5px;" vspace="0" width="5">
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="article OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-heading-text" style="color: #5BC6CC; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 18px; font-weight: bold; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div>
<div>Hi {{name}}!</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-text" style="color: #1f1f1f; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div style=";">
<div><span style="color: rgb(153, 153, 153); font-size: 20px; font-weight: bold;"></span>
</div>
<div>
{{content}}
</div>
<div>
<br>
</div>
<div>
<br>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="article OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-text" style="color: #1f1f1f; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div style=";">
<div><span style="color: rgb(153, 153, 153); font-size: 20px; font-weight: bold;"></span>
</div>
<div>
<br>
</div>
<div>Warmest regard,
</div>
<div>
<br>
</div>
<div>
<br>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="" class="OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-divider">
<table border="0" cellpadding="0" cellspacing="0" class="editor-divider" width="100%">
<tbody>
<tr>
<td align="center" class="" valign="top">
<table class="galileo-ap-content-editor" style="cursor: default;" width="100%">
<tbody>
<tr>
<td align="center" class="divider-base divider-solid" style="padding: 9px 0;" valign="top" width="100%">
<table align="center" border="0" cellpadding="0" cellspacing="0" style="height: 1px; width: 94%;">
<tbody>
<tr>
<td align="center" bgcolor="#5BC6CC" height="1" style="background: #5BC6CC; border-bottom-style: none; height: 1px; line-height: 1px; padding-bottom: 0px;">
<div>
<img alt="" border="0" height="1" hspace="0" src="https://imgssl.constantcontact.com/letters/images/1101116784221/S.gif" style="display: block; height: 1px; width: 5px;" vspace="0" width="5">
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="galileo-ap-layout-editor" width="100%">
<tbody>
<tr>
<td align="left" class="article OneColumnMobile column" valign="top" width="100%">
<div class="gl-contains-text">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" class="editor-text article-text" style="color: #1f1f1f; display: block; font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 14px; padding: 10px 20px; text-align: left; word-wrap: break-word;" valign="top">
<div>
</div>
<div style=";">
<div align="center" style="text-align: center;">
<div style=";">
<span style="font-size: 10px;">Copyright iCondo. All Rights Reserved.</span>
</div>
<div>
<div>
<p>
<span style="font-size: 10px;">We take your privacy very seriously, click to view our&nbsp;</span><span style="font-size: 10px;"><span
style="font-size: 10px;"><span
style="color: #5BC6CC;">privacy policy</span><span style="font-size: 10px;">.</span></span>
</span>
</p>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
import * as Promise from "bluebird";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus, jwt, mailer, JsonMapper } from "../../../../libs";
import { ArticlesModel, ExceptionModel, StateModel, SessionModel } from "../../../../models";
import { PROPERTIES } from "../../../../libs/constants";
import { roleService, categoryService } from "../../../../interactors";
export class ArticlesHandler extends BaseHandler {
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
queryParams.roleId = session.roleId;
return categoryService.search(queryParams, offset, limit, [], ["isDeleted"])
.then(category => {
res.header(PROPERTIES.HEADER_TOTAL, category.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(category.data);
})
.catch(err => {
next(err);
});
}
/**
* checkConstraintField
* @param data
* @param isUpdated
* @returns {boolean}
*/
public static checkConstraintField(data: ArticlesModel): boolean {
let result = true;
if (!data.name || !data.id) {
result = false;
}
return result;
}
public static create(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(ArticlesModel, req.body);
if (ArticlesHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return categoryService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* remove role, delete
* @param req
* @param res
* @param next
* @returns {any}
*/
public static delete(req: express.Request, res: express.Response, next: express.NextFunction): any {
let roleId = req.params.id || "";
return categoryService.removeById(roleId)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
}
/**
* @param req
* @param res
* @param next
* @returns {any}
*/
public static update(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(ArticlesModel, req.body);
obj.id = req.params.id;
if (ArticlesHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return Promise.resolve(true)
.then(() => {
return categoryService.update(obj, [], ["isDeleted"]);
})
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
}
import { isAuthenticated } from "./../../../../middlewares/index";
import * as express from "express";
import { ArticlesHandler } from "./articles.handler";
const router = express.Router();
router.route("/")
.get(isAuthenticated, ArticlesHandler.list)
.post(isAuthenticated, ArticlesHandler.create);
router.route("/:id")
.delete(isAuthenticated, ArticlesHandler.delete)
.put(isAuthenticated, ArticlesHandler.update);
export default router;
import * as Promise from "bluebird";
import * as Schema from "../../../../data/sql/schema";
import * as express from "express";
import { ErrorCode, HttpStatus, JsonMapper } from "../../../../libs";
import { ExceptionModel, StateModel, ApplicationModel } from "../../../../models";
import { PROPERTIES } from "../../../../libs/constants";
import { QueryBuilder } from "knex";
import { devOpsService } from "../../../../interactors";
export class ApplicationHandler {
/**
* get list
* @param req
* @param res
* @param next
* @returns {any}
*/
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let params = req.query || {};
return devOpsService.listAppVersion(params, offset, limit, ["isDeleted", "isEnable", "createdDate", "updatedDate"])
.then(result => {
res.header(PROPERTIES.HEADER_TOTAL, result.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(result.data);
})
.catch(err => {
next(err);
});
}
public static create(req: express.Request, res: express.Response, next: express.NextFunction): any {
let application = JsonMapper.deserialize(ApplicationModel, req.body);
return devOpsService.insert(application)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
if (!(err instanceof ExceptionModel)) {
err = new ExceptionModel(
ErrorCode.RESOURCE.GENERIC.CODE,
err.message,
false,
HttpStatus.BAD_GATEWAY
);
}
next(err);
});
}
public static update(req: express.Request, res: express.Response, next: express.NextFunction): any {
let application = JsonMapper.deserialize(ApplicationModel, req.body);
application.id = req.params.id;
if (!application.id) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return devOpsService.update(application)
.then(result => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(application.id));
})
.catch(err => {
next(err);
});
}
public static delete(req: express.Request, res: express.Response, next: express.NextFunction): any {
let applicationId = req.params.id;
return devOpsService.forceDelete(applicationId)
.then((success) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful(applicationId));
})
.catch(err => {
next(err);
});
}
}
export default ApplicationHandler;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { ApplicationHandler } from "./application.handler";
import { isAuthenticated, hasPrivilege, hasCache } from "../../../../middlewares";
import { ROLE } from "../../../../libs/constants";
const router = express.Router();
router.route("/")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN]), hasCache(), ApplicationHandler.list)
.post(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN]), hasCache(), ApplicationHandler.create);
router.route("/:id")
.put(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN]), hasCache(), ApplicationHandler.update)
.delete(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN]), hasCache(), ApplicationHandler.delete);
export default router;
import { } from "./../../../../libs/mapper/json.mapper";
import * as express from "express";
import { DeviceModel, ExceptionModel, SessionModel, UserModel, StateModel } from "../../../../models";
import { ErrorCode, HttpStatus, logger, firebase, JsonMapper } from "../../../../libs";
import { PROPERTIES, JWT_WEB_TOKEN, ROLE, FIREBASE_ONLINE_STATUS } from "../../../../libs/constants";
import { userService, deviceService, sessionService } from "../../../../interactors";
import { database } from "firebase-admin";
export class AuthHandler {
public static firebaseLogin(req: express.Request, res: express.Response, next: express.NextFunction): void {
let session: SessionModel = res.locals.session || SessionModel.empty();
sessionService.createFirebaseToken(session.userId)
.then((token) => {
res.status(HttpStatus.OK);
res.json({
token: token,
});
})
.catch(err => next(err));
}
/**
*
* @param req
* @param res
* @param next
*/
public static login(req: express.Request, res: express.Response, next: express.NextFunction): void {
let email = req.body.email || "";
let password = req.body.password || "";
let roleId: string;
let userInfo: UserModel;
let sessionInfo: SessionModel;
let deviceModel: DeviceModel;
if (AuthHandler.checkConstraintField(req.body) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
userService.verifyLoginPrudential(email, password, ["isEnable", "isDeleted"])
.then(object => {
userInfo = object;
roleId = object.roleId;
deviceModel = DeviceModel.fromRequest(req.headers, object.id);
if (deviceModel.userAgent === PROPERTIES.MOBILE_USER_AGENT) {
return deviceService.create(deviceModel);
} else {
return deviceModel;
}
})
.then(object => {
deviceModel = object;
return sessionService.create(userInfo.id, userInfo.roleId, JWT_WEB_TOKEN.DEFAULT_EXPIRE, object.deviceId, ["hash"]);
})
.then(session => {
UserModel.filters(userInfo, ["password"]);
session.user = userInfo;
sessionInfo = session;
return sessionService.createFirebaseToken(userInfo.id, userInfo, deviceModel)
.catch(err => logger.error(err.message, err));
})
.then(token => {
sessionInfo.firebaseToken = token;
res.status(HttpStatus.OK);
res.json(sessionInfo.toResponse());
})
.catch(err => {
next(err);
});
}
public static register(req: express.Request, res: express.Response, next: express.NextFunction) {
let roleId: string;
let user: UserModel;
let session: SessionModel;
let device: DeviceModel;
if (AuthHandler.checkConstraintField(req.body) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
user = JsonMapper.deserialize(UserModel, req.body);
user.roleId = ROLE.USER;
userService.create(user, [], ["password"])
.then(object => {
user = object;
device = DeviceModel.fromRequest(req.headers, user.id);
if (device.userAgent === PROPERTIES.MOBILE_USER_AGENT) {
return deviceService.create(device);
} else {
return device;
}
})
.then(object => {
device = object;
return sessionService.create(user.id, user.roleId, JWT_WEB_TOKEN.DEFAULT_EXPIRE, object.deviceId, ["hash"]);
})
.then(object => {
session = object;
UserModel.filters(user, ["password"]);
session.user = user;
return sessionService.createFirebaseToken(user.id, user, device)
.catch(err => logger.error(err.message, err));
})
.then(token => {
session.firebaseToken = token;
res.status(HttpStatus.OK);
res.json(session.toResponse());
})
.catch(err => {
next(err);
});
}
/**
*
* @param data
* @param loginType
* @returns {boolean}
*/
private static checkConstraintField(data: any) {
let result = true;
if (data.email === "" || data.password === "") {
result = false;
}
return result;
}
/**
* logout
* @param req
* @param res
* @param next
*/
public static logout(req: express.Request, res: express.Response, next: express.NextFunction): void {
let session = res.locals.session || SessionModel.empty();
let deviceModel = DeviceModel.fromRequest(req.headers, session.userId);
sessionService.deleteSessionByUserId(session.userId, session.hash)
.then(() => {
let sdk = firebase.getInstance();
if (sdk != null) {
// Remove the device token into firebase.
if (deviceModel != null && deviceModel.deviceId != null && deviceModel.registrarId != null) {
sdk.database()
.ref("/devices")
.child(session.userId)
.child(`${deviceModel.deviceId}`)
.remove()
.catch(err => logger.error(err.message, err));
}
// Update online status for user after logout on firebase.
sdk.database()
.ref("/users")
.child(session.userId)
.update({
online: FIREBASE_ONLINE_STATUS.OFFLINE,
updatedDate: database.ServerValue.TIMESTAMP
})
.catch(err => logger.error(err.message, err));
}
return deviceService.deleteByUserId(session.userId, deviceModel.deviceId);
})
.then(() => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(error => {
next(error);
});
}
}
export default AuthHandler;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { AuthHandler } from "./auth.handler";
import { isAuthenticated, hasPrivilege } from "../../../../middlewares";
import { ROLE } from "../../../../libs/constants";
const router = express.Router();
router.route("/login")
.post(AuthHandler.login);
router.route("/register")
.post(AuthHandler.register);
router.route("/firebase")
.post(isAuthenticated, AuthHandler.firebaseLogin);
router.route("/logout")
.post(isAuthenticated, hasPrivilege([ROLE.USER]), AuthHandler.logout);
export default router;
/**
* Created by phuongho on 15/08/17.
*/
import * as _ from "lodash";
export class BaseHandler {
public static clean(model: any): any {
let prune = (current) => {
_.forOwn(current, (value, key) => {
if (_.isNull(value) ||
_.isNaN(value) ||
(_.isString(value) && _.isEmpty(value)) ||
value === "null" ||
(_.isObject(value) && _.isEmpty(prune(value)))) {
current[key] = undefined;
}
});
// remove any leftover undefined values from the delete
// operation on an array
if (_.isArray(current)) {
_.pull(current, undefined);
}
return current;
};
return prune(_.cloneDeep(model));
}
}
export default BaseHandler;
import * as Promise from "bluebird";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus, jwt, mailer, JsonMapper } from "../../../../libs";
import { CategoryModel, ExceptionModel, StateModel, SessionModel } from "../../../../models";
import { PROPERTIES } from "../../../../libs/constants";
import { roleService, categoryService } from "../../../../interactors";
export class CategoryHandler extends BaseHandler {
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
queryParams.roleId = session.roleId;
return categoryService.search(queryParams, offset, limit, [], ["isDeleted"])
.then(category => {
res.header(PROPERTIES.HEADER_TOTAL, category.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(category.data);
})
.catch(err => {
next(err);
});
}
/**
* checkConstraintField
* @param data
* @param isUpdated
* @returns {boolean}
*/
public static checkConstraintField(data: CategoryModel): boolean {
let result = true;
if (!data.name) {
result = false;
}
return result;
}
public static create(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(CategoryModel, req.body);
if (CategoryHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return categoryService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* remove role, delete
* @param req
* @param res
* @param next
* @returns {any}
*/
public static delete(req: express.Request, res: express.Response, next: express.NextFunction): any {
let roleId = req.params.id || "";
return categoryService.removeById(roleId)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
}
/**
* @param req
* @param res
* @param next
* @returns {any}
*/
public static update(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(CategoryModel, req.body);
obj.id = req.params.id;
if (CategoryHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return Promise.resolve(true)
.then(() => {
return categoryService.update(obj, [], ["isDeleted"]);
})
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
}
import { isAuthenticated } from "./../../../../middlewares/index";
import * as express from "express";
import { CategoryHandler } from "./category.handler";
const router = express.Router();
router.route("/")
.get(CategoryHandler.list)
.post(CategoryHandler.create);
router.route("/:id")
.delete(isAuthenticated, CategoryHandler.delete)
.put(isAuthenticated, CategoryHandler.update);
export default router;
const cityLib = require("cities/locations");
import * as Promise from "bluebird";
import * as _ from "lodash";
import * as countryLib from "countryjs";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { CountryModel } from "../../../../models";
import { ErrorCode, HttpStatus } from "../../../../libs";
export class CountryHandler extends BaseHandler {
/**
*
* @param req
* @param res
* @param next
*/
public static listCountry(req: express.Request, res: express.Response, next: express.NextFunction) {
let countryJson = countryLib.all();
Promise.resolve()
.then(() => {
return countryLib.all();
})
.then(objects => {
let arr: CountryModel[] = [];
for (let i = 0; i < objects.length; i++) {
if (objects[i].name != null) {
let temp = new CountryModel();
temp.name = objects[i].name;
temp.code = objects[i].ISO.alpha2.toString().toLowerCase();
arr.push(temp);
}
}
res.status(HttpStatus.OK);
res.json(arr);
})
.catch(err => {
next(err);
});
}
/**
*
* @param req
* @param res
* @param next
*/
public static listStates(req: express.Request, res: express.Response, next: express.NextFunction) {
let countryCode: string = req.params.countryCode;
countryCode = countryCode.toString().toUpperCase();
Promise.resolve()
.then(() => {
return countryLib.states(countryCode);
})
.then(objects => {
res.status(HttpStatus.OK);
if (objects == null) {
res.json([]);
} else {
res.json(objects);
}
})
.catch(err => {
next(err);
});
}
/**
*
* @param req
* @param res
* @param next
*/
public static listProvinces(req: express.Request, res: express.Response, next: express.NextFunction) {
let stateCode: string = req.params.stateCode;
Promise.resolve()
.then(() => {
return _.filter(cityLib, { state: stateCode });
})
.then(objects => {
let ret: any = [];
objects.forEach((item: any) => {
if (item.city && ret.indexOf(item.city) === -1) {
ret.push(item.city);
}
});
res.status(HttpStatus.OK);
res.json(ret);
})
.catch(err => {
next(err);
});
}
}
import * as express from "express";
import { CountryHandler } from "./country.handler";
const router = express.Router();
router.route("/states/:countryCode")
.get(CountryHandler.listStates);
router.route("/provinces/:stateCode")
.get(CountryHandler.listProvinces);
router.route("/")
.get(CountryHandler.listCountry);
export default router;
/**
* Created by phuongho on 15/08/17.
*/
import * as Promise from "bluebird";
import * as Schema from "../../../../data/sql/schema";
import * as express from "express";
import { BaseDto } from "../../../../data/sql/models";
import { HttpStatus } from "../../../../libs";
import { Redis } from "../../../../data/redis/redis";
export class HealthHandler {
public static check(req: express.Request, res: express.Response, next: express.NextFunction): any {
let checkDatabase = () => {
return BaseDto.knex().raw("SELECT * FROM health").then(result => {
return result.rows;
});
};
let checkRedis = () => {
return Redis.getClient().setAsync("health", 1);
};
return Promise.all([checkDatabase(), checkRedis()])
.then(result => {
res.status(HttpStatus.OK);
res.send("OK");
})
.catch(err => {
next(err);
});
}
}
export default HealthHandler;
/**
* Created by phuongho on 15/08/17.
*/
import { HealthHandler } from "./health.handler";
import * as express from "express";
const router = express.Router();
router.route("/")
.get(HealthHandler.check);
export default router;
import { Language } from "./../../../libs/languages/language";
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import application from "./application/application.router";
import auth from "./auth/auth.router";
import country from "./country/country.router";
import health from "./health/health.router";
import me from "./me/me.router";
import media from "./media/media.router";
import packages from "./packages/packages.router";
import presentations from "./presentations/presentation.router";
import roles from "./roles/roles.router";
import settings from "./settings/settings.router";
import tags from "./tags/tags.router";
import userCode from "./user_code/user_code.router";
import users from "./users/users.router";
import languages from "./languages/language.router";
import category from "./category/category.router";
const router = express.Router();
router.use("/application", application);
router.use("/auth", auth);
router.use("/country", country);
router.use("/health", health);
router.use("/me", me);
router.use("/media", media);
router.use("/packages", packages);
router.use("/presentations", presentations);
router.use("/roles", roles);
router.use("/settings", settings);
router.use("/tags", tags);
router.use("/user_codes", userCode);
router.use("/users", users);
router.use("/languages", languages);
router.use("/category", category);
export default router;
import * as Promise from "bluebird";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus, jwt, mailer, JsonMapper } from "../../../../libs";
import { LanguageModel, ExceptionModel, StateModel, SessionModel } from "../../../../models";
import { PROPERTIES } from "../../../../libs/constants";
import { roleService, languageService } from "../../../../interactors";
export class LanguageHandler extends BaseHandler {
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
queryParams.roleId = session.roleId;
return languageService.search(queryParams, offset, limit, [], ["isDeleted"])
.then(languages => {
res.header(PROPERTIES.HEADER_TOTAL, languages.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(languages.data);
})
.catch(err => {
next(err);
});
}
/**
* checkConstraintField
* @param data
* @param isUpdated
* @returns {boolean}
*/
public static checkConstraintField(data: LanguageModel): boolean {
let result = true;
if (!data.name || !data.code) {
result = false;
}
return result;
}
public static create(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(LanguageModel, req.body);
if (LanguageHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return languageService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* remove role, delete
* @param req
* @param res
* @param next
* @returns {any}
*/
public static delete(req: express.Request, res: express.Response, next: express.NextFunction): any {
let roleId = req.params.id || "";
return languageService.removeById(roleId)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
}
/**
* @param req
* @param res
* @param next
* @returns {any}
*/
public static update(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(LanguageModel, req.body);
obj.id = req.params.id;
if (LanguageHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return Promise.resolve(true)
.then(() => {
return languageService.update(obj, [], ["isDeleted"]);
})
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
}
import { isAuthenticated } from "./../../../../middlewares/index";
import { Language } from "./../../../../libs/languages/language";
import * as express from "express";
import { LanguageHandler } from "./language.handler";
const router = express.Router();
router.route("/")
.get(isAuthenticated, LanguageHandler.list)
.post(isAuthenticated, LanguageHandler.create);
router.route("/:id")
.delete(isAuthenticated, LanguageHandler.delete)
.put(isAuthenticated, LanguageHandler.update);
export default router;
import * as Promise from "bluebird";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus, Utils, JsonMapper } from "../../../../libs";
import { ExceptionModel, StateModel, SessionModel, DeviceModel, UserModel } from "../../../../models";
import { JWT_WEB_TOKEN } from "../../../../libs/constants";
import { userService, sessionService, deviceService } from "../../../../interactors";
export class MeHandler extends BaseHandler {
/**
*
* @param req
* @param res
* @param next
*/
public static profile(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
return userService.detailById(session.userId, ["role"], ["isDeleted", "password"])
.then(role => {
res.status(HttpStatus.OK);
res.json(role);
})
.catch(err => {
next(err);
});
}
public static updateProfile(req: express.Request, res: express.Response, next: express.NextFunction): any {
try {
let session = res.locals.session || SessionModel.empty();
let user = JsonMapper.deserialize(UserModel, req.body);
user.id = session.userId;
user.email = undefined;
user.roleId = undefined;
user.parentId = undefined;
// Prevent change user password, if you wan to change, use changePassword() instead
user.password = undefined;
return userService.updateMyProfile(user)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
} catch (err) {
next(err);
}
}
/**
*
* @param req
* @param res
* @param next
*/
public static changePassword(req: express.Request, res: express.Response, next: express.NextFunction): any {
try {
let session = res.locals.session || SessionModel.empty();
let oldPassword = req.body.oldPassword || null;
let newPassword = req.body.newPassword || null;
let userInfo: UserModel;
if (oldPassword == null || newPassword == null) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
if (!Utils.validatePassword(newPassword)) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.INVALID_PASSWORD.CODE,
ErrorCode.RESOURCE.INVALID_PASSWORD.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
let deviceModel = DeviceModel.fromRequest(req.headers, session.userId);
return userService.changePassword(session.userId, oldPassword, newPassword, ["role"], ["password"])
.then(obj => {
userInfo = obj;
if (deviceModel.deviceId != null && deviceModel.registrarId != null) {
return deviceService.create(deviceModel);
} else {
return deviceModel;
}
})
.then(() => {
return sessionService.create(userInfo.id, userInfo.roleId, JWT_WEB_TOKEN.DEFAULT_EXPIRE, deviceModel.deviceId, ["hash"]);
})
.then(session => {
UserModel.filters(userInfo, ["password"]);
session.user = userInfo;
res.status(HttpStatus.OK);
res.json(session);
})
.catch(err => {
next(err);
});
} catch (err) {
next(err);
}
}
}
export default MeHandler;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { MeHandler } from "./me.handler";
import { isAuthenticated, hasPrivilege, hasCache } from "../../../../middlewares";
import { ROLE } from "../../../../libs/constants";
const router = express.Router();
router.route("/password")
.put(isAuthenticated, MeHandler.changePassword);
router.route("/")
.get(isAuthenticated, MeHandler.profile)
.put(isAuthenticated, MeHandler.updateProfile);
export default router;
import * as Promise from "bluebird";
import * as UUID from "uuid";
import * as express from "express";
import * as formidable from "formidable";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus, uploader, JsonMapper } from "../../../../libs";
import { MediaModel, ExceptionModel } from "../../../../models";
import { mediaService } from "../../../../interactors";
export class MediaHandler extends BaseHandler {
/**
*
* @param req
* @param res
* @param next
*/
public static checkHash(req: express.Request, res: express.Response, next: express.NextFunction) {
try {
return Promise.resolve()
.then(() => {
return mediaService.findByHash(req.query.hash);
})
.then((wrapper) => {
res.json(wrapper.data);
})
.catch(err => next(err));
} catch (err) {
next(err);
}
}
/**
*
* @param req
* @param res
* @param next
*/
public static update(req: express.Request, res: express.Response, next: express.NextFunction) {
try {
let media = JsonMapper.deserialize(MediaModel, req.body);
return Promise.resolve()
.then(() => {
return mediaService.make(media);
})
.then(() => {
res.end();
})
.catch(err => next(err));
} catch (err) {
next(err);
}
}
/**
*
* @param req
* @param res
* @param next
*/
public static newFile(req: express.Request, res: express.Response, next: express.NextFunction) {
try {
let form = new formidable.IncomingForm();
form.parse(req, (err: any, fields: formidable.Fields, files: formidable.Files) => {
let file = files["file"];
if (file == null || file.path == null || file.name == null || !fields.type) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST
));
}
return Promise.resolve()
.then(() => {
let fileName = file.name.split(".");
let ext = fileName[fileName.length - 1];
if (fields && fields.type) {
if (fields.type !== ext) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.INVALID_FILE_UPLOAD.CODE,
ErrorCode.RESOURCE.INVALID_FILE_UPLOAD.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
}
let name = UUID.v4();
return uploader.uploadFile(file.path, `${name}.${ext}`);
})
.then(object => {
let media = MediaModel.fromDataS3(object);
return mediaService.make(media, [], ["isEnable", "isDeleted"]);
})
.then(object => {
res.status(HttpStatus.OK);
res.json(object);
})
.catch(err => {
next(err);
});
});
} catch (err) {
next(err);
}
}
}
export default MediaHandler;
/**
* Created by phuongho on 15/08/17.
*/
import { MediaHandler } from "./media.handler";
import * as express from "express";
import { isAuthenticated } from "../../../../middlewares";
const router = express.Router();
router.route("/callback")
.get(MediaHandler.checkHash)
.post(MediaHandler.update);
router.route("/files")
.post(isAuthenticated, MediaHandler.newFile);
export default router;
import * as Promise from "bluebird";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus, JsonMapper } from "../../../../libs";
import { ExceptionModel, StateModel, PackageModel, SessionModel, UserPackageModel } from "../../../../models";
import { PROPERTIES } from "../../../../libs/constants";
import { packageService, userPackageService } from "../../../../interactors";
export class PackageHandler extends BaseHandler {
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
return packageService.search(queryParams, offset, limit, [], ["isDeleted"])
.then(packages => {
res.header(PROPERTIES.HEADER_TOTAL, packages.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(JsonMapper.serialize(packages.data));
})
.catch(err => {
next(err);
});
}
public static detail(req: express.Request, res: express.Response, next: express.NextFunction) {
return packageService.detailById(req.params.id, [], ["isDeleted"])
.then(role => {
res.status(HttpStatus.OK);
res.json(role);
})
.catch(err => {
next(err);
});
}
/**
* Create role
* @param req
* @param res
* @param next
* @returns {any}
*/
public static create(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(PackageModel, req.body);
if (PackageHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return packageService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* Edit role: use for super admin and condo manage
* @param req
* @param res
* @param next
* @returns {any}
*/
public static edit(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(PackageModel, req.body);
obj.id = req.params.id;
if (PackageHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return Promise.resolve(true)
.then(() => {
return packageService.update(obj);
})
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* remove role, delete
* @param req
* @param res
* @param next
* @returns {any}
*/
public static delete(req: express.Request, res: express.Response, next: express.NextFunction): any {
let roleId = req.params.id || "";
return packageService.removeById(roleId)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
}
/**
* checkConstraintField
* @param data
* @param isUpdated
* @returns {boolean}
*/
public static checkConstraintField(data: PackageModel): boolean {
let result = true;
if (!data.name || !data.numberAccount || !data.numberFile) {
result = false;
}
return result;
}
public static userPackages(req: express.Request, res: express.Response, next: express.NextFunction) {
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
return userPackageService.search(queryParams, offset, limit, ["package", "user"])
.then(packages => {
res.header(PROPERTIES.HEADER_TOTAL, packages.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(JsonMapper.serialize(packages.data));
})
.catch(err => {
next(err);
});
}
public static createUserPackage(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(UserPackageModel, req.body);
if (PackageHandler.checkConstraintUserPackageField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return userPackageService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
public static updateUserPackage(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(UserPackageModel, req.body);
obj.id = req.params.id;
if (PackageHandler.checkConstraintUserPackageField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return userPackageService.update(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
*
* @param req
* @param res
* @param next
*/
public static deleteUserPackage(req: express.Request, res: express.Response, next: express.NextFunction): any {
let roleId = req.params.id || "";
return userPackageService.removeById(roleId)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
}
public static checkConstraintUserPackageField(data: UserPackageModel): boolean {
let result = true;
if (!data.userId || !data.packageId) {
result = false;
}
return result;
}
}
export default PackageHandler;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { PackageHandler } from "./packages.handler";
import { isAuthenticated, hasPrivilege, hasCache } from "../../../../middlewares";
import { ROLE } from "../../../../libs/constants";
const router = express.Router();
router.route("/order")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), PackageHandler.userPackages)
.post(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER]), PackageHandler.createUserPackage);
router.route("/order/:id")
.put(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER]), PackageHandler.updateUserPackage)
.delete(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER]), PackageHandler.deleteUserPackage);
router.route("/:id")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER]), PackageHandler.detail)
.put(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER]), PackageHandler.edit)
.delete(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER]), PackageHandler.delete);
router.route("/")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER]), PackageHandler.list)
.post(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER]), PackageHandler.create);
export default router;
import * as Promise from "bluebird";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus, JsonMapper } from "../../../../libs";
import { ExceptionModel, AssignPresentationModel, StateModel, PresentationModel, SessionModel } from "../../../../models";
import { presentationService, assignPresentationService } from "../../../../interactors";
import { ROLE, PROPERTIES } from "../../../../libs/constants";
export class PresentationHandler extends BaseHandler {
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
queryParams.roleId = session.roleId;
if (session.roleId === ROLE.COMPANY_ADMIN || session.roleId === ROLE.PRESENTER) {
queryParams.userId = session.userId;
}
if (session.roleId === ROLE.OPERATOR) {
if (!queryParams.userId) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
}
return presentationService.search(queryParams, offset, limit, [], ["isDeleted"])
.then(Presentations => {
res.header(PROPERTIES.HEADER_TOTAL, Presentations.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(Presentations.data);
})
.catch(err => {
next(err);
});
}
public static detail(req: express.Request, res: express.Response, next: express.NextFunction) {
return presentationService.detailById(req.params.id, [], ["isDeleted"])
.then(role => {
res.status(HttpStatus.OK);
res.json(role);
})
.catch(err => {
next(err);
});
}
/**
* Create presentation
* @param req
* @param res
* @param next
* @returns {any}
*/
public static create(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(PresentationModel, req.body);
if (PresentationHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return presentationService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* Edit presentation
* @param req
* @param res
* @param next
* @returns {any}
*/
public static edit(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(PresentationModel, req.body);
obj.id = req.params.id;
if (PresentationHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
obj.userId = undefined;
obj.userCode = undefined;
return Promise.resolve(true)
.then(() => {
return presentationService.update(obj);
})
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* remove presentation, delete
* @param req
* @param res
* @param next
* @returns {any}
*/
public static delete(req: express.Request, res: express.Response, next: express.NextFunction): any {
let roleId = req.params.id || "";
return presentationService.removeById(roleId)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
}
/**
* checkConstraintField
* @param data
* @param isUpdated
* @returns {boolean}
*/
public static checkConstraintField(data: PresentationModel): boolean {
let result = true;
if (!data.title || !data.userId || !data.userCode || !data.numberPage || !data.pageTiming || !data.fileUrl || !data.imageUrl) {
result = false;
}
return result;
}
public static assign(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(AssignPresentationModel, req.body);
obj.presentationId = req.params.id;
if (PresentationHandler.checkAssignConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return assignPresentationService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
*
* @param data
*/
public static checkAssignConstraintField(data: AssignPresentationModel): boolean {
let result = true;
if (!data.presentationId || (!data.tags && !data.country) || !data.users) {
result = false;
}
return result;
}
/**
*
* @param req
* @param res
* @param next
*/
public static assignDetail(req: express.Request, res: express.Response, next: express.NextFunction) {
return assignPresentationService.detailByPresentaionId(req.params.id, [], ["isDeleted"])
.then(object => {
res.status(HttpStatus.OK);
res.json(object ? object : {} );
})
.catch(err => {
next(err);
});
}
}
export default PresentationHandler;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { PresentationHandler } from "./presentation.handler";
import { isAuthenticated, hasPrivilege, hasCache } from "../../../../middlewares";
import { ROLE } from "../../../../libs/constants";
const router = express.Router();
router.route("/assign/:id")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), PresentationHandler.assignDetail)
.post(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), PresentationHandler.assign);
router.route("/:id")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), PresentationHandler.detail)
.put(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), PresentationHandler.edit)
.delete(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), PresentationHandler.delete);
router.route("/")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR, ROLE.PRESENTER]), PresentationHandler.list)
.post(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), PresentationHandler.create);
export default router;
import * as Promise from "bluebird";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus} from "../../../../libs";
import { ExceptionModel, StateModel, RoleModel, SessionModel } from "../../../../models";
import { JsonMapper } from "./../../../../libs/mapper/json.mapper";
import { PROPERTIES } from "../../../../libs/constants";
import { roleService } from "../../../../interactors";
export class RoleHandler extends BaseHandler {
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
queryParams.roleId = session.roleId;
return roleService.search(queryParams, offset, limit, [], ["isDeleted"])
.then(roles => {
res.header(PROPERTIES.HEADER_TOTAL, roles.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(roles.data);
})
.catch(err => {
next(err);
});
}
public static detail(req: express.Request, res: express.Response, next: express.NextFunction) {
return roleService.detailById(req.params.id, [], ["isDeleted"])
.then(role => {
res.status(HttpStatus.OK);
res.json(role);
})
.catch(err => {
next(err);
});
}
/**
* Create role
* @param req
* @param res
* @param next
* @returns {any}
*/
public static create(req: express.Request, res: express.Response, next: express.NextFunction): any {
let obj = JsonMapper.deserialize(RoleModel, req.body);
if (RoleHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
obj.id = obj.name.replace(/ /, "_").toString().toLowerCase();
return roleService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* Edit role: use for super admin and condo manage
* @param req
* @param res
* @param next
* @returns {any}
*/
public static edit(req: express.Request, res: express.Response, next: express.NextFunction): any {
let obj = JsonMapper.deserialize(RoleModel, req.body);
obj.id = req.params.id;
if (RoleHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return Promise.resolve(true)
.then(() => {
return roleService.update(obj);
})
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* remove role, delete
* @param req
* @param res
* @param next
* @returns {any}
*/
public static delete(req: express.Request, res: express.Response, next: express.NextFunction): any {
let roleId = req.params.id || "";
return roleService.removeById(roleId)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
}
/**
* checkConstraintField
* @param data
* @param isUpdated
* @returns {boolean}
*/
public static checkConstraintField(data: RoleModel): boolean {
let result = true;
if (!data.name) {
result = false;
}
return result;
}
}
export default RoleHandler;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { RoleHandler } from "./roles.handler";
import { isAuthenticated, hasPrivilege, hasCache } from "../../../../middlewares";
import { ROLE } from "../../../../libs/constants";
const router = express.Router();
router.route("/:id")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), RoleHandler.detail)
.put(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), RoleHandler.edit)
.delete(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), RoleHandler.delete);
router.route("/")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), RoleHandler.list)
.post(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), RoleHandler.create);
export default router;
/**
* Created by davidho on 2/12/17.
*/
import * as Promise from "bluebird";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus , JsonMapper} from "../../../../libs";
import { ExceptionModel, SessionModel } from "../../../../models";
import { ROLE, PROPERTIES } from "../../../../libs/constants";
import { SettingModel, StateModel } from "../../../../models";
import { settingService } from "../../../../interactors";
export class SettingHandler extends BaseHandler {
/**
* create
* @param req
* @param res
* @param next
* @returns {any}
*/
public static create(req: express.Request, res: express.Response, next: express.NextFunction): any {
try {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(SettingModel, req.body);
if (SettingHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return settingService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
} catch (err) {
next(err);
}
}
/**
*
* @param req
* @param res
* @param next
*/
public static edit(req: express.Request, res: express.Response, next: express.NextFunction): any {
try {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(SettingModel, req.body);
obj.id = req.params.id || "";
if (SettingHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
obj.keyword = undefined; // ignore update keyword
return settingService.update(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
} catch (err) {
next(err);
}
}
/**
*
* @param req
* @param res
* @param next
*/
public static remove(req: express.Request, res: express.Response, next: express.NextFunction): any {
try {
let session = res.locals.session || SessionModel.empty();
let id = req.params.id || "";
return settingService.removeById(id)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
} catch (err) {
next(err);
}
}
/**
* get list
* @param req
* @param res
* @param next
* @returns {any}
*/
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
try {
let session = res.locals.session || SessionModel.empty();
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
return settingService.search(queryParams, offset, limit, null, ["isDeleted", "isEnable"])
.then(users => {
res.header(PROPERTIES.HEADER_TOTAL, users.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(users.data);
})
.catch(err => {
next(err);
});
} catch (err) {
next(err);
}
}
/**
*
* @param data
* @returns {boolean}
*/
public static checkConstraintField(data: SettingModel): boolean {
let result = true;
if (!data.keyword || !data.value || !data.desc) {
result = false;
}
return result;
}
}
export default SettingHandler;
/**
* Created by davidho on 2/12/17.
*/
import { SettingHandler } from "./settings.handler";
import * as express from "express";
import { isAuthenticated, hasPrivilege, hasCache } from "../../../../middlewares";
import { ROLE } from "../../../../libs/constants";
const router = express.Router();
router.route("/:id")
.put(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN]), SettingHandler.edit)
.delete(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN]), SettingHandler.remove);
router.route("/")
.get(isAuthenticated, SettingHandler.list)
.post(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN]), SettingHandler.create);
export default router;
import { ROLE } from "./../../../../libs/constants";
import * as Promise from "bluebird";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus, JsonMapper} from "../../../../libs";
import { ExceptionModel, StateModel, TagModel, SessionModel, DeviceModel } from "../../../../models";
import { PROPERTIES } from "../../../../libs/constants";
import { tagService } from "../../../../interactors";
export class TagHandler extends BaseHandler {
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
if (session.roleId === ROLE.COMPANY_ADMIN) {
queryParams.userId = session.userId;
}
if (session.roleId === ROLE.OPERATOR) {
if (!queryParams.userId) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
}
return tagService.search(queryParams, offset, limit, [], ["isDeleted"])
.then(tags => {
res.header(PROPERTIES.HEADER_TOTAL, tags.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(tags.data);
})
.catch(err => {
next(err);
});
}
public static detail(req: express.Request, res: express.Response, next: express.NextFunction) {
return tagService.detailById(req.params.id, [], ["isDeleted"])
.then(role => {
res.status(HttpStatus.OK);
res.json(role);
})
.catch(err => {
next(err);
});
}
/**
* Create role
* @param req
* @param res
* @param next
* @returns {any}
*/
public static create(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(TagModel, req.body);
if (TagHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return tagService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* Edit role: use for super admin and condo manage
* @param req
* @param res
* @param next
* @returns {any}
*/
public static edit(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(TagModel, req.body);
obj.id = req.params.id;
if (TagHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return Promise.resolve(true)
.then(() => {
return tagService.update(obj);
})
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* remove role, delete
* @param req
* @param res
* @param next
* @returns {any}
*/
public static delete(req: express.Request, res: express.Response, next: express.NextFunction): any {
let roleId = req.params.id || "";
return tagService.removeById(roleId)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
}
/**
* checkConstraintField
* @param data
* @param isUpdated
* @returns {boolean}
*/
public static checkConstraintField(data: TagModel): boolean {
let result = true;
if (!data.name || !data.userId) {
result = false;
}
return result;
}
}
export default TagHandler;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { TagHandler } from "./tags.handler";
import { isAuthenticated, hasPrivilege, hasCache } from "../../../../middlewares";
import { ROLE } from "../../../../libs/constants";
const router = express.Router();
router.route("/:id")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), TagHandler.detail)
.put(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), TagHandler.edit)
.delete(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), TagHandler.delete);
router.route("/")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), TagHandler.list)
.post(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), TagHandler.create);
export default router;
import { ROLE } from "./../../../../libs/constants";
import * as Promise from "bluebird";
import * as UUID from "uuid";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus, JsonMapper } from "../../../../libs";
import { ExceptionModel, StateModel, UserCodeModel, SessionModel } from "../../../../models";
import { PROPERTIES } from "../../../../libs/constants";
import { userCodeService } from "../../../../interactors";
export class UserCodeHandler extends BaseHandler {
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
if (session.roleId === ROLE.COMPANY_ADMIN) {
queryParams.userId = session.userId;
}
if (session.roleId === ROLE.OPERATOR) {
if (!queryParams.userId) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
}
return userCodeService.search(queryParams, offset, limit, [], ["isDeleted"])
.then(UserCodes => {
res.header(PROPERTIES.HEADER_TOTAL, UserCodes.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(UserCodes.data);
})
.catch(err => {
next(err);
});
}
public static detail(req: express.Request, res: express.Response, next: express.NextFunction) {
return userCodeService.detailById(req.params.id, [], ["isDeleted"])
.then(role => {
res.status(HttpStatus.OK);
res.json(role);
})
.catch(err => {
next(err);
});
}
/**
* Create role
* @param req
* @param res
* @param next
* @returns {any}
*/
public static create(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(UserCodeModel, req.body);
obj.code = UUID.v4();
if (UserCodeHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return userCodeService.create(obj)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* Edit role: use for super admin and condo manage
* @param req
* @param res
* @param next
* @returns {any}
*/
public static edit(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let obj = JsonMapper.deserialize(UserCodeModel, req.body);
obj.id = req.params.id;
if (UserCodeHandler.checkConstraintField(obj) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
return Promise.resolve(true)
.then(() => {
return userCodeService.update(obj);
})
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* remove role, delete
* @param req
* @param res
* @param next
* @returns {any}
*/
public static delete(req: express.Request, res: express.Response, next: express.NextFunction): any {
let roleId = req.params.id || "";
return userCodeService.removeById(roleId)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
}
/**
* checkConstraintField
* @param data
* @param isUpdated
* @returns {boolean}
*/
public static checkConstraintField(data: UserCodeModel): boolean {
let result = true;
if (!data.name || !data.userId) {
result = false;
}
return result;
}
}
export default UserCodeHandler;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { UserCodeHandler } from "./user_code.handler";
import { isAuthenticated, hasPrivilege, hasCache } from "../../../../middlewares";
import { ROLE } from "../../../../libs/constants";
const router = express.Router();
router.route("/:id")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), UserCodeHandler.detail)
.put(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), UserCodeHandler.edit)
.delete(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), UserCodeHandler.delete);
router.route("/")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), UserCodeHandler.list)
.post(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN]), UserCodeHandler.create);
export default router;
import * as Promise from "bluebird";
import * as express from "express";
import { BaseHandler } from "../base.handler";
import { ErrorCode, HttpStatus, Utils, jwt, JsonWebToken, mailer, JsonMapper, BookshelfMapper, logger } from "../../../../libs";
import { ExceptionModel, StateModel, UserModel, SessionModel, DeviceModel } from "../../../../models";
import { FIREBASE_ONLINE_STATUS } from "./../../../../libs/constants";
import { PROPERTIES, ROLE, MESSAGE_INFO, PASSWORD_LENGTH, EMAIL_TEMPLATE } from "../../../../libs/constants";
import { database } from "firebase-admin";
import { firebase as FirebaseAdmin } from "./../../../../libs";
import { sessionService, userService, deviceService } from "../../../../interactors";
export class UserHandler extends BaseHandler {
/**
* logout
* @param req
* @param res
* @param next
*/
public static logout(req: express.Request, res: express.Response, next: express.NextFunction): void {
try {
let session = res.locals.session || SessionModel.empty();
let deviceModel = DeviceModel.fromRequest(req.headers, session.userId);
sessionService.deleteSessionByUserId(session.userId, session.hash)
.then(() => {
let sdk = FirebaseAdmin.getInstance();
if (sdk != null) {
// Remove the device token into firebase.
if (deviceModel != null && deviceModel.deviceId != null && deviceModel.registrarId != null) {
sdk.database()
.ref("/devices")
.child(session.userId)
.child(`${deviceModel.deviceId}`)
.remove()
.catch(err => logger.error(err.message, err));
}
// Update online status for user after logout on firebase.
sdk.database()
.ref("/users")
.child(session.userId)
.update({
online: FIREBASE_ONLINE_STATUS.OFFLINE,
updatedDate: database.ServerValue.TIMESTAMP
})
.catch(err => logger.error(err.message, err));
}
return deviceService.deleteByUserId(session.userId, deviceModel.deviceId);
})
.then(() => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(error => {
next(error);
});
} catch (err) {
next(err);
}
}
public static list(req: express.Request, res: express.Response, next: express.NextFunction) {
let session = res.locals.session || SessionModel.empty();
let offset = parseInt(req.query.offset, 10) || null;
let limit = parseInt(req.query.limit, 10) || null;
let queryParams = req.query || null;
if (session.roleId === ROLE.COMPANY_ADMIN) {
queryParams.parentId = session.userId;
}
if (session.roleId === ROLE.OPERATOR) {
if (!queryParams.parentId) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
}
queryParams.currentUserId = session.userId;
return userService.search(queryParams, offset, limit, ["role", "userPackage.package", "userTag"], ["password"])
.then(users => {
res.header(PROPERTIES.HEADER_TOTAL, users.total.toString(10));
if (offset != null) {
res.header(PROPERTIES.HEADER_OFFSET, offset.toString(10));
}
if (limit != null) {
res.header(PROPERTIES.HEADER_LIMIT, limit.toString(10));
}
res.status(HttpStatus.OK);
res.json(JsonMapper.serialize(users.data));
})
.catch(err => {
next(err);
});
}
public static detail(req: express.Request, res: express.Response, next: express.NextFunction) {
return userService.detailById(req.params.id, [], ["password", "isDeleted"])
.then(user => {
res.status(HttpStatus.OK);
res.json(JsonMapper.serialize(user));
})
.catch(err => {
next(err);
});
}
/**
* checkConstraintField
* @param data
* @param isUpdated
* @returns {boolean}
*/
public static checkConstraintField(data: UserModel): boolean {
let result = true;
if (!data.id) {
if (!data.password) {
result = false;
}
}
if (!data.firstName || !data.lastName || !data.roleId || !data.email) {
result = false;
}
if (data.roleId === ROLE.OPERATOR || data.roleId === ROLE.PRESENTER) {
if (!data.parentId) {
result = false;
}
}
return result;
}
/**
* Create user in portal
* @param req
* @param res
* @param next
* @returns {any}
*/
public static create(req: express.Request, res: express.Response, next: express.NextFunction): any {
let session = res.locals.session || SessionModel.empty();
let user = JsonMapper.deserialize(UserModel, req.body);
if (UserHandler.checkConstraintField(user) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
if (!Utils.validateEmail(user.email)) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.INVALID_EMAIL_FORMAT.CODE,
ErrorCode.RESOURCE.INVALID_EMAIL_FORMAT.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
if (user.roleId !== ROLE.OPERATOR && user.roleId !== ROLE.PRESENTER) {
user.parentId = undefined;
}
if (user.roleId !== ROLE.PRESENTER) {
user.tags = undefined;
}
return userService.create(user)
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.createSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* forgot password
* @param req
* @param res
* @param next
* @returns {any}
*/
public static forgotPassword(req: express.Request, res: express.Response, next: express.NextFunction): any {
let email = req.body.email || "";
if (email === "") {
return next(new ExceptionModel(
ErrorCode.RESOURCE.EMPTY_EMAIL.CODE,
ErrorCode.RESOURCE.EMPTY_EMAIL.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
let link = `${req.protocol}://${req.get("host")}/api/v1/users/forgotpassword`;
return userService.forgotPassword(email, link)
.then((object) => {
if (object === true) {
res.status(HttpStatus.OK);
res.json(StateModel.resetPasswordSuccessful());
}
})
.catch(err => {
next(err);
});
}
public static resetPassword(req: express.Request, res: express.Response, next: express.NextFunction): any {
let message = {
body: {
name: "",
intro: MESSAGE_INFO.MI_RESET_PASSWORD_TOKEN_INVALID
}
};
res.header("Content-Type", "text/html; charset=UTF-8");
let token = req.params.token || "";
let password = `${Utils.randomPassword(PASSWORD_LENGTH)}`;
let email: string;
let userId = "";
return Promise.resolve()
.then(() => {
if (jwt.verify(token, JsonWebToken.DEFAULT_CLIENT)) {
let jwtObject = jwt.decode(token);
let current = Date.now();
if (current < jwtObject.exp) {
let userId = jwtObject.payload.userId;
return userService.findOne(userId);
}
message.body.intro = MESSAGE_INFO.MI_RESET_PASSWORD_EXPIRED;
}
return Promise.reject(false);
})
.then(user => {
if (user == null) {
return Promise.reject(false);
}
userId = user.id;
message.body.name = user.name;
email = user.email;
return userService.setPassword(user.id, password);
})
.then(object => {
// send new password to user
let user = BookshelfMapper.deserialize(UserModel, object);
mailer.sendNewPassword(user, password);
message.body.intro = MESSAGE_INFO.MI_CHECK_EMAIL_FOR_NEW_PASSWORD;
mailer.generateCustomHtml({
template: EMAIL_TEMPLATE.SEND_CUSTOM_EMAIL,
data: {
name: message.body.name,
content: message.body.intro,
}
}).then((data: any) => {
res.send(data.html);
});
})
.catch(() => {
mailer.generateCustomHtml({
template: EMAIL_TEMPLATE.SEND_CUSTOM_EMAIL,
data: {
name: message.body.name,
content: message.body.intro,
}
}).then((data: any) => {
res.send(data.html);
});
});
}
/**
* Edit user: use for super admin and condo manage
* @param req
* @param res
* @param next
* @returns {any}
*/
public static edit(req: express.Request, res: express.Response, next: express.NextFunction): any {
let user = JsonMapper.deserialize(UserModel, req.body);
user.id = req.params.id;
if (UserHandler.checkConstraintField(user) === false) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.CODE,
ErrorCode.RESOURCE.MISSING_REQUIRED_FIELDS.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
if (!Utils.validateEmail(user.email)) {
return next(new ExceptionModel(
ErrorCode.RESOURCE.INVALID_EMAIL_FORMAT.CODE,
ErrorCode.RESOURCE.INVALID_EMAIL_FORMAT.MESSAGE,
false,
HttpStatus.BAD_REQUEST,
));
}
if (user.roleId !== ROLE.OPERATOR && user.roleId !== ROLE.PRESENTER) {
user.parentId = undefined;
}
if (user.roleId !== ROLE.PRESENTER) {
user.tags = undefined;
}
return Promise.resolve(true)
.then(() => {
if (user.password) { // if admin change password user, user have to re-login
return sessionService.deleteSessionByUserId(user.id);
}
})
.then(() => {
return userService.update(user);
})
.then(object => {
res.status(HttpStatus.OK);
res.json(StateModel.updateSuccessful(object.id));
})
.catch(err => {
next(err);
});
}
/**
* remove user, delete
* @param req
* @param res
* @param next
* @returns {any}
*/
public static delete(req: express.Request, res: express.Response, next: express.NextFunction): any {
let userId = req.params.id || "";
return userService.removeById(userId)
.then((object) => {
res.status(HttpStatus.OK);
res.json(StateModel.deleteSuccessful());
})
.catch(err => {
next(err);
});
}
}
export default UserHandler;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import { UserHandler } from "./users.handler";
import { isAuthenticated, hasPrivilege, hasCache } from "../../../../middlewares";
import { ROLE } from "../../../../libs/constants";
const router = express.Router();
router.route("/logout")
.post(isAuthenticated, UserHandler.logout);
router.route("/forgotpassword")
.post(UserHandler.forgotPassword);
router.route("/forgotpassword/:token")
.get(UserHandler.resetPassword);
router.route("/:id")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), UserHandler.detail)
.put(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), UserHandler.edit)
.delete(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), UserHandler.delete);
router.route("/")
.get(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), UserHandler.list)
.post(isAuthenticated, hasPrivilege([ROLE.SYSTEM_ADMIN, ROLE.MANAGER, ROLE.COMPANY_ADMIN, ROLE.OPERATOR]), UserHandler.create);
export default router;
/**
* Created by phuongho on 15/08/17.
*/
import * as express from "express";
import api from "./api/v1";
const router = express.Router();
router.get("/ping", (req: express.Request, res: express.Response, next: express.NextFunction) => {
res.end();
});
router.get("/favicon.ico", (req: express.Request, res: express.Response) => {
res.status(404);
res.end();
});
router.use("/api/v1", api);
export default router;
/**
* Created by phuongho on 15/08/17.
*/
import * as dotEnv from "dotenv";
import * as sourceMapSupport from "source-map-support";
import Application from "./app";
import { config, logger } from "./libs";
if (process.env.NODE_ENV !== "production") {
sourceMapSupport.install();
}
dotEnv.config({ });
// Bootstrap new app
new Application(logger, logger.getTransportLogger()).listen(config.port);
/**
* Created by kiettv on 12/16/16.
*/
import "mocha";
import * as chai from "chai";
const chaiHttp = require("chai-http");
import {Application} from "../src/app";
process.env.NODE_ENV = "test";
chai.use(chaiHttp);
const expect = chai.expect;
const app = chai.request(new Application().getExpressInstance());
describe("Route", () => {
it("Should be json", () => {
app.get("/ping")
.then(res => {
expect(res.type).to.eql("application/json");
});
});
it("Should response Not Found", () => {
app.get("/")
.then(res => {
expect(res.status).eq(400);
});
});
});
--compilers ts-node/register
--full-trace
--bail
test/**/*.spec.ts
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "build",
"allowJs": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]
}
{
"rules": {
"class-name": true,
"comment-format": [true, "check-space"],
"indent": [true, "spaces"],
"no-duplicate-variable": true,
"no-eval": true,
"no-internal-module": true,
"no-trailing-whitespace": true,
"no-var-keyword": true,
"one-line": [true, "check-open-brace", "check-whitespace"],
"quotemark": [true, "double"],
"semicolon": [true],
"triple-equals": [true, "allow-null-check"],
"typedef-whitespace": [true, {
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}],
"variable-name": [true, "ban-keywords"],
"whitespace": [true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
},
"jsRules": {
"indent": [true, "spaces"],
"no-duplicate-variable": true,
"no-eval": true,
"no-trailing-whitespace": true,
"one-line": [true, "check-open-brace", "check-whitespace"],
"quotemark": [true, "double"],
"semicolon": [true],
"triple-equals": [true, "allow-null-check"],
"variable-name": [true, "ban-keywords"],
"whitespace": [true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment