├── start.sh ├── .babelrc ├── gitpush.sh ├── .gitignore ├── model ├── Test.js ├── index.js └── User.js ├── env.example ├── docker-compose.yml ├── routes ├── auth.js ├── test.js └── user.js ├── Dockerfile ├── ecosystem.config.js ├── common ├── connectDB.js ├── constants.js ├── onesignal.js └── function.js ├── .eslintrc ├── README.md ├── controller ├── index.js ├── test.js ├── auth.js └── user.js ├── locales ├── vi.json └── en.json ├── LICENSE ├── index.js └── package.json /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | node dist/index.js 3 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015" 4 | ] 5 | } -------------------------------------------------------------------------------- /gitpush.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | git add . 4 | read -p "input message: " mess 5 | git commit -m "$mess" 6 | git push 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | yarn-error.log 3 | dist/ 4 | .env 5 | db.text 6 | runUpdate.sh 7 | updateCode.sh 8 | 9 | node_modules 10 | -------------------------------------------------------------------------------- /model/Test.js: -------------------------------------------------------------------------------- 1 | import { defaultModel, statusActive, timeType } from '../common/constants' 2 | 3 | export default { 4 | name: defaultModel.string, 5 | status: defaultModel.string 6 | } 7 | -------------------------------------------------------------------------------- /env.example: -------------------------------------------------------------------------------- 1 | PORT=3031 2 | 3 | # Database connection 4 | IS_DEV=false 5 | DB_NAME=nameDB 6 | 7 | # URL Connect Local 8 | DB_URL=127.0.0.1:27017 9 | 10 | #secret token ( authen by jwt) 11 | SECRET_TOKEN=dummyProject -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | web: 4 | build: . 5 | environment: 6 | - REDIS_HOST=redis 7 | ports: 8 | - "3000:3000" 9 | depends_on: 10 | - redis 11 | redis: 12 | image: redis -------------------------------------------------------------------------------- /routes/auth.js: -------------------------------------------------------------------------------- 1 | import AuthServices from '../controller/auth' 2 | const express = require('express') 3 | const router = express.Router() 4 | 5 | router.post('/login', AuthServices.login) 6 | router.post('/register' , AuthServices.register) 7 | // router.post('/forgot-password', AuthServices.forgotPassword) 8 | router.put('/change-password', AuthServices.changePassword) 9 | 10 | module.exports = router -------------------------------------------------------------------------------- /routes/test.js: -------------------------------------------------------------------------------- 1 | import TestServices from '../controller/test' 2 | const express = require('express') 3 | const router = express.Router() 4 | 5 | router.get('/', TestServices.get) 6 | router.get('/me/:id' , TestServices.getById) 7 | router.post('/', TestServices.create) 8 | router.put('/', TestServices.update) 9 | router.delete('/', TestServices.delete) 10 | 11 | module.exports = router 12 | 13 | 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10.16.0-alpine AS builder 2 | WORKDIR /usr/src/app 3 | COPY package.json yarn.lock ./ 4 | COPY . . 5 | RUN npm install --production 6 | RUN npm run build:prod 7 | FROM node:10.16.0-alpine 8 | WORKDIR /usr/src/app 9 | COPY --from=builder /usr/src/app/node_modules/. ./node_modules 10 | COPY --from=builder /usr/src/app/dist/. ./dist 11 | COPY ./package.json ./package.json 12 | CMD [ "npm","run","start:prod" ] -------------------------------------------------------------------------------- /ecosystem.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | apps: [ 3 | { 4 | name: 'ec2021', 5 | script: 'dist/index.js', 6 | args: 'index.js', 7 | wait_ready: true, 8 | error_file: './logs/err.log', 9 | out_file: './logs/out.log', 10 | log_file: './logs/combined.log', 11 | log_date_format: 'YYYY-MM-DD HH:mm:ss:SSSS', 12 | min_uptime: 10000, 13 | max_restarts: 3, 14 | }, 15 | ], 16 | }; -------------------------------------------------------------------------------- /model/index.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose' 2 | 3 | import UserSchema from './User' 4 | import TestSchema from './Test' 5 | 6 | 7 | const Schema = mongoose.Schema 8 | 9 | const createSchema = (schema) => { 10 | const model = new Schema(schema, { timestamps: true }) 11 | return model 12 | } 13 | 14 | const User = mongoose.model('User', createSchema(UserSchema)) 15 | const Test = mongoose.model('Test', createSchema(TestSchema)) 16 | 17 | 18 | export { 19 | User, 20 | Test 21 | } 22 | 23 | -------------------------------------------------------------------------------- /common/connectDB.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose' 2 | 3 | export const connectDatabase = () => { 4 | mongoose.Promise = require('bluebird') 5 | mongoose.connect(`${process.env.DB_URL}`, { 6 | //mongoose.connect(`mongodb://${process.env.DB_URL}/${process.env.DB_NAME}`, { 7 | useUnifiedTopology: true, 8 | useFindAndModify: false, 9 | useNewUrlParser: true, 10 | useCreateIndex: true 11 | }) 12 | .then(async () => { 13 | console.log('EC2 Database connection created') 14 | }).catch((err) => { 15 | console.log(err) 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": [ 4 | "eslint:recommended", 5 | "standard" 6 | ], 7 | "env": { 8 | "jest": true 9 | }, 10 | "plugins": [ 11 | "flowtype-errors" 12 | ], 13 | "parserOptions": { 14 | "ecmaFeatures": { 15 | "jsx": true 16 | } 17 | }, 18 | "rules": { 19 | "no-undef": "error", 20 | "indent": [ 21 | 2, 22 | 2 23 | ] 24 | }, 25 | "globals": { 26 | "fetch": true, 27 | "enquire": true, 28 | "FontFaceObserver": true, 29 | "imagesloaded": true, 30 | "Modernizr": true 31 | } 32 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Ecommerce Backend Project 2 | 3 | ### Description :tada: :100: 4 | - The requirement of this project is build a ecommerce system using nodejs and mongodb for backend and mobile using flutter for developement. :plane: 5 | 6 | ### How I can run it? 7 | - :rocket: Clone this project 8 | - :rocket: Touch .env file and import follow env.example 9 | - :rocket: Install all dependencies using yarn or npm 10 | - :rocket: Okay, setup done. Now, you can run and import to them...:tada: 11 | 12 | ### Deadline :calendar: 13 | - :rocket: 06/2021 14 | 15 | ### Author: 16 | - :rocket: lamhan3012cmvn 17 | - :rocket: lambiengcode 18 | -------------------------------------------------------------------------------- /model/User.js: -------------------------------------------------------------------------------- 1 | import { defaultModel, userRole, statusActive, gender, providerType } from '../common/constants' 2 | 3 | export default { 4 | id: defaultModel.string, 5 | fullName: defaultModel.string, 6 | email: defaultModel.string, 7 | image: defaultModel.string, 8 | gender: { type: String, default: gender.other }, 9 | phone: defaultModel.string, 10 | address: defaultModel.string, 11 | status: { type: String, default: statusActive.active }, 12 | password: defaultModel.string, 13 | role: { type: String, default: userRole.member }, 14 | provider: { type: String, default: providerType.null }, 15 | nonce: defaultModel.number, 16 | } 17 | -------------------------------------------------------------------------------- /routes/user.js: -------------------------------------------------------------------------------- 1 | 2 | import UserServices from '../controller/user' 3 | const express = require('express') 4 | const router = express.Router() 5 | 6 | router.get('/profile', UserServices.get) 7 | router.get('/me/:id', UserServices.getById) 8 | router.get('/count', UserServices.count) 9 | router.get('/checkUser/:id', UserServices.checkUser) 10 | 11 | router.post('/reg/pw', UserServices.postLoginPassword) 12 | router.post('/reg/fb', UserServices.postLoginFacebook) 13 | router.post('/reg/gg', UserServices.postLoginGoogle) 14 | router.post('/login', UserServices.loginPassword) 15 | 16 | // router.put('/pwChange', UserServices.changePassword) 17 | router.put('/', UserServices.update) 18 | router.delete('/', UserServices.delete) 19 | 20 | module.exports = router 21 | -------------------------------------------------------------------------------- /controller/index.js: -------------------------------------------------------------------------------- 1 | import { verifyToken, decodeToken, lowerCase } from '../common/function' 2 | 3 | export default class BaseAPI { 4 | static verifyResult (output, init = []) { 5 | if (!output) { 6 | return init 7 | } else { 8 | return output 9 | } 10 | } 11 | 12 | static async authorizationAPI (req, res, runAction, isCheckSignature) { 13 | try { 14 | const tokenAuthen = req.get('Authorization').replace('Bearer ', '') 15 | if (verifyToken(tokenAuthen)) { 16 | const user = lowerCase(decodeToken(tokenAuthen)) 17 | runAction(user) 18 | } else { 19 | res.status(401).send('Authentication failed, please contact to Ush admin if you have any questions') 20 | } 21 | } catch (error) { 22 | res.status(500).send('error :' + error) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /locales/vi.json: -------------------------------------------------------------------------------- 1 | { 2 | "pressStartTelegram": "Ấn lệnh Start để lấy mã xác nhận", 3 | "yourCodeIs": "Mã của bạn là {{value}}", 4 | "yourVerifyCode": "Mã OTP Coin98: {code}", 5 | "receiveCoin": "Bạn đã nhận được {{coin}} từ {{name}}", 6 | "kudoSend": "{{name}} Kudos tới {{post}} của bạn {{coin}}", 7 | "newReward": "{{name}} đã có mặt trên cửa hàng", 8 | "updateReward": "{{name}} đã cập nhật thông tin", 9 | "newLiked": "{{name}} vừa thích {{post}} của bạn", 10 | "alreadyLinkTele": "Telegram của bạn đã được liên kết", 11 | "newComment": "{{name}} vừa bình luận bài viết của bạn", 12 | "newShip": "{{name}} của bạn đã được chuyển đi", 13 | "newContribute": "Đóng góp ý tưởng mới từ {{name}}", 14 | "newSwap": "{{name}} đã Swap {{coin}} sang {{coin2}}", 15 | "refReceived": "Bạn được tặng {{coin}} bởi giới thiệu thành công {{name}}", 16 | "refIntroduced": "Tặng Ref: Giới thiệu {{name}}", 17 | "refBy": "Tặng Ref: Giới thiệu bởi {{name}}", 18 | "refMission": "Thưởng giới thiệu từ {{name}} - Nhiệm vụ {{mission}}" 19 | } -------------------------------------------------------------------------------- /locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "pressStartTelegram": "Press Start command to get verification code", 3 | "yourCodeIs": "Your code is {{code}}", 4 | "yourVerifyCode": "Coin98 OTP code: {code}", 5 | "receiveCoin": "You received {{coin}} from {{name}}", 6 | "kudoSend": "{{name}} Kudos to your {{post}} {{coin}}", 7 | "newReward": "{{name}} is now available on Reward Store", 8 | "updateReward": "{{name}} has updated information", 9 | "newLiked": "{{name}} liked your {{post}}", 10 | "alreadyLinkTele": "Your Telegram account already linked", 11 | "newComment": "{{name}} commented on your post", 12 | "newShip": "Your {{name}} has been shipped", 13 | "newContribute": "Contribute new ideas from {{name}}", 14 | "newSwap": "{{name}} has swapped {{coin}} to {{coin2}}", 15 | "refReceived": "You received {{coin}} for successfully introducing {{name}}", 16 | "refIntroduced": "Ref Bonus: Introduced {{name}}", 17 | "refBy": "Ref Bonus: Introduced by {{name}}", 18 | "refMission": "Referral Bonus by {{name}} - {{mission}} Earn Mission" 19 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Dao Hong Vinh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import http from 'http' 2 | import cors from 'cors' 3 | import express from 'express' 4 | import bodyParser from 'body-parser' 5 | import morgan from 'morgan' 6 | import helmet from 'helmet' 7 | import cookieParser from 'cookie-parser' 8 | import { connectDatabase } from './common/connectDB' 9 | // Routes 10 | import Auth from './routes/auth' 11 | import User from './routes/user' 12 | import Test from './routes/test' 13 | 14 | import i18n from 'i18n' 15 | require('dotenv').config() 16 | 17 | // Setup server express 18 | const app = express() 19 | 20 | app.use(morgan('dev')) 21 | app.use(helmet()) 22 | app.use(cors()) 23 | app.use(bodyParser.json({ limit: '100mb' })) 24 | app.use(bodyParser.urlencoded({ limit: '100mb', extended: true })) 25 | app.use(cookieParser()) 26 | 27 | app.get('/api/info', (req, res) => { 28 | res.json('welcome to test !') 29 | }) 30 | 31 | app.use('/auth', Auth) 32 | app.use('/api/user', User) 33 | app.use('/api/test', Test) 34 | 35 | // error handler 36 | app.use(function (err, req, res, next) { 37 | if (err.isBoom) { 38 | return res.status(err.output.statusCode).json(err.output.payload) 39 | } 40 | }) 41 | 42 | i18n.configure({ 43 | locales: ['en', 'vi'], 44 | directory: './locales' 45 | }) 46 | 47 | const server = http.createServer(app) 48 | 49 | // Database connection 50 | connectDatabase() 51 | 52 | server.listen(process.env.PORT) 53 | 54 | console.log('Server run on port ' + process.env.PORT) 55 | -------------------------------------------------------------------------------- /common/constants.js: -------------------------------------------------------------------------------- 1 | export const optionsSocket = { 2 | /* socket.io options */ 3 | reconnection: true, 4 | reconnectionDelay: 1000, 5 | reconnectionDelayMax: 5000, 6 | reconnectionAttempts: Infinity 7 | } 8 | 9 | export const sendGridId = { 10 | resetPassword: 'd-6600ae71c5324523b12ade29e081c815', 11 | signUp: 'd-6bbac4cb42d14c338c3504599ebb8bf0', 12 | contactUs: 'd-61a468ea9e5d41d88827f49f02699584' 13 | 14 | } 15 | 16 | export const reactionType = { 17 | follow: 'follow', 18 | like: 'like', 19 | bad: 'bad', 20 | good: 'good' 21 | } 22 | 23 | export const typeDevice = { 24 | LIGHT: 'LIGHT', 25 | FAN: 'FAN' 26 | } 27 | 28 | export const timeType = { 29 | oneTime: 'oneTime', 30 | loop: 'loop' 31 | } 32 | 33 | export const providerType = { 34 | facebook: 'facebook', 35 | google: 'google', 36 | null: null 37 | } 38 | 39 | export const categoryType = { 40 | normal: 'normal' 41 | } 42 | 43 | export const userRole = { 44 | admin: 'admin', 45 | member: 'member', 46 | moderator: 'moderator' 47 | } 48 | 49 | export const gender = { 50 | male: 'MALE', 51 | female: 'FEMALE', 52 | other: 'OTHER' 53 | } 54 | 55 | export const statusActive = { 56 | inactive: 'INACTIVE', 57 | active: 'ACTIVE', 58 | deleted: 'DELETED' 59 | } 60 | 61 | export const defaultModel = { 62 | date: { type: Date }, 63 | string: { type: String, default: '' }, 64 | stringUnique: { type: String, required: true, unique: true }, 65 | array: { type: Array, default: [] }, 66 | number: { type: Number, default: 0 }, 67 | boolean: { type: Boolean, default: true }, 68 | booleanFalse: { type: Boolean, default: false }, 69 | object: { type: Object, default: {} } 70 | } 71 | 72 | export const optionsCcxt = { 73 | apiKey: process.env.FMX_API_KEY, 74 | secret: process.env.FMX_SECRET_KEY 75 | } 76 | -------------------------------------------------------------------------------- /controller/test.js: -------------------------------------------------------------------------------- 1 | import BaseAPI from '.' 2 | import { Test } from '../model' 3 | import { genUpdate, generateID } from '../common/function' 4 | 5 | export default class TestServices { 6 | 7 | static async getById (req,res){ 8 | const id = req.params.id 9 | const payload = await Test.findOne({_id :id }) 10 | res.json(payload) 11 | } 12 | 13 | static async get (req, res) { 14 | BaseAPI.authorizationAPI(req, res, async () => { 15 | const payload = await Test.find({status: 'ACTIVE'}) 16 | res.json(payload) 17 | }) 18 | } 19 | 20 | static async create (req, res) { 21 | BaseAPI.authorizationAPI(req, res, async (createdUser) => { 22 | try { 23 | const { name, status } = req.body 24 | const payload = await Test.create({ name, status }) 25 | res.json(payload) 26 | } catch (error) { 27 | res.send('error :' + error) 28 | } 29 | }) 30 | } 31 | 32 | static async update (req, res) { 33 | BaseAPI.authorizationAPI(req, res, async () => { 34 | try { 35 | const { id } = req.body 36 | const updateField = genUpdate(req.body, ['name', 'status']) 37 | await Test.findOneAndUpdate({ _id : id }, updateField, { new: true }, async (err, result) => { 38 | if (!err || result) { 39 | res.json(result) 40 | } else { 41 | res.json(false) 42 | } 43 | }) 44 | } catch (error) { 45 | res.status(500).send('error :' + error) 46 | } 47 | }) 48 | } 49 | 50 | 51 | static async delete (req, res) { 52 | BaseAPI.authorizationAPI(req, res, async () => { 53 | try { 54 | const { id } = req.body 55 | await Test.findOneAndUpdate({ _id : id }, { status: 'DELETED' }, { new: true }, async (err, result) => { 56 | if (result || !err) { 57 | res.json(result) 58 | } else { 59 | res.json(false) 60 | } 61 | }) 62 | } catch (error) { 63 | res.send('error :' + error) 64 | } 65 | }) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ush", 3 | "version": "1.0.0", 4 | "description": "ush server", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "rimraf dist/ && babel ./ --out-dir dist/ --ignore ./node_modules,./.babelrc,./package.json,./npm-console.log.log --copy-files", 8 | "build:prod": "babel ./ --out-dir dist/ --ignore ./node_modules,./.babelrc,./package.json,./npm-console.log.log --copy-files", 9 | "start": "npm run build && node dist/index.js", 10 | "start:prod": "node dist/index.js", 11 | "dev": "nodemon --exec babel-node index.js", 12 | "pm2": "yarn build && yarn pm2:start", 13 | "pm2:start": "pm2 start ecosystem.config.js" 14 | }, 15 | "author": "lambiengcode", 16 | "license": "ISC", 17 | "dependencies": { 18 | "@hapi/joi": "^17.1.1", 19 | "@vitalets/google-translate-api": "^5.0.0", 20 | "aws-sdk": "^2.543.0", 21 | "axios": "^0.21.1", 22 | "bigdecimal": "^0.6.1", 23 | "blockcypher": "^0.2.0", 24 | "bluebird": "^3.7.0", 25 | "body-parser": "^1.19.0", 26 | "ccxt": "^1.24.86", 27 | "ccxws": "^0.31.0", 28 | "cookie-parser": "^1.4.4", 29 | "cors": "^2.8.5", 30 | "cron-converter": "^1.0.0", 31 | "cron-job-manager": "^2.1.2", 32 | "cron-parser": "^2.13.0", 33 | "crypto-js": "^3.1.9-1", 34 | "dotenv": "^8.1.0", 35 | "ethereum-input-data-decoder": "^0.0.17", 36 | "ethers": "^4.0.38", 37 | "express": "^4.17.1", 38 | "express-joi-validation": "^4.0.3", 39 | "express-joi-validator": "^2.0.1", 40 | "express-rate-limit": "^5.0.0", 41 | "fb": "^2.0.0", 42 | "formidable": "^1.2.2", 43 | "grabity": "^1.0.5", 44 | "helmet": "^3.21.1", 45 | "hex2dec": "^1.1.2", 46 | "i18n": "^0.8.3", 47 | "joi": "^14.3.1", 48 | "js-base64": "^2.5.1", 49 | "jsonwebtoken": "^8.5.1", 50 | "moment": "^2.24.0", 51 | "mongoose": "5.7.3", 52 | "morgan": "^1.9.1", 53 | "multer": "^1.4.2", 54 | "nexmo": "^2.5.2", 55 | "node-fetch": "^2.6.0", 56 | "numbro": "^2.1.2", 57 | "onesignal-node": "^2.1.1", 58 | "query-string": "^6.8.3", 59 | "request-ip": "^2.1.3", 60 | "request-promise": "^4.2.5", 61 | "saslprep": "^1.0.3", 62 | "socket.io": "^2.4.1", 63 | "socket.io-client": "^2.3.0", 64 | "telegraf": "^3.34.1", 65 | "twitter": "^1.7.1", 66 | "uuid": "^3.4.0", 67 | "wavecell-sdk": "^1.0.2", 68 | "ws": "^7.2.3", 69 | "xlsx": "^0.15.6" 70 | }, 71 | "devDependencies": { 72 | "babel-cli": "^6.18.0", 73 | "babel-eslint": "^10.0.3", 74 | "babel-preset-es2015": "^6.24.1", 75 | "eslint": "6.5.1", 76 | "eslint-config-standard": "^14.1.0", 77 | "eslint-plugin-flowtype-errors": "4.1.0", 78 | "eslint-plugin-import": "^2.18.2", 79 | "eslint-plugin-node": "^10.0.0", 80 | "eslint-plugin-promise": "^4.2.1", 81 | "eslint-plugin-standard": "^4.0.1", 82 | "flow-bin": "^0.109.0", 83 | "nodemon": "^1.19.3", 84 | "rimraf": "^3.0.0" 85 | }, 86 | "engines": { 87 | "node": ">=12.0.0", 88 | "yarn": ">=1.19.0" 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /common/onesignal.js: -------------------------------------------------------------------------------- 1 | import OneSignal from 'onesignal-node' 2 | import { logDebug, getLength } from '../common/function' 3 | import i18n from 'i18n' 4 | import NotificationServices from '../controller/notification' 5 | import UserServices from '../controller/user' 6 | 7 | // create a new client for a single app 8 | const oneSignalClient = new OneSignal.Client({ 9 | userAuthKey: '', 10 | app: { 11 | appAuthKey: '', 12 | appId: '' 13 | } 14 | }) 15 | 16 | export const generateLanguage = (phrase, locale = 'en', replace) => { 17 | const langGenerate = (i18n.__({ phrase, locale: locale === 'en' ? 'en' : 'vi' }, replace)).replace('/', '/') 18 | return langGenerate === phrase ? generateLanguage(phrase, locale, replace) : langGenerate 19 | } 20 | 21 | const sendMessageFilter = (arrMess, locale) => { 22 | let message 23 | 24 | const data = arrMess[1] 25 | 26 | switch (arrMess[0]) { 27 | case -1: 28 | message = data[0] 29 | break 30 | case 1: 31 | message = generateLanguage('newReward', locale, { name: data[0] }) 32 | break 33 | case 2: 34 | message = generateLanguage('newShip', locale, { name: data[0] }) 35 | break 36 | case 3: 37 | message = generateLanguage('newContribute', locale, { name: data[0] }) 38 | break 39 | case 4: 40 | message = generateLanguage('newSwap', locale, { name: data[0], coin: data[1], coin2: data[2] }) 41 | break 42 | case 5: 43 | message = generateLanguage('receiveCoin', locale, { coin: data[0], name: data[1] }) 44 | break 45 | case 6: 46 | message = generateLanguage('kudoSend', locale, { name: data[0], coin: data[1], post: data[2] }) 47 | break 48 | case 7: 49 | message = generateLanguage('newLiked', locale, { name: data[0], post: data[1] }) 50 | break 51 | case 8: 52 | message = generateLanguage('newComment', locale, { name: data[0] }) 53 | break 54 | case 9: 55 | message = generateLanguage('refIntroduced', locale, { name: data[0] }) 56 | break 57 | case 10: 58 | message = generateLanguage('refBy', locale, { name: data[0] }) 59 | break 60 | case 11: 61 | message = generateLanguage('updateReward', locale, { name: data[0] }) 62 | break 63 | case 12: 64 | message = generateLanguage('refMission', locale, { name: data[0], mission: data[1] }) 65 | break 66 | } 67 | 68 | return message 69 | } 70 | 71 | export const sendNotiToUser = async (message, data, type, userId, isEnVi, image, header) => { 72 | const userDevice = await UserServices.getDeviceIDByID(userId) 73 | if (userDevice) { 74 | const localeUser = userDevice.locale === 'en' ? 'en' : 'vi' 75 | 76 | console.log({ message: [type, isEnVi ? [message[localeUser]] : message], locale: localeUser }, userDevice.deviceId, data, userDevice.id, header, image) 77 | sendNotifications({ message: [type, isEnVi ? [message[localeUser]] : message], locale: localeUser }, userDevice.deviceId, data, userDevice.id, header, image) 78 | } 79 | } 80 | 81 | export const sendNotiList = async (list, locale, message, data, image) => { 82 | const listUserSend = await UserServices.getDeviceByList(list, locale) 83 | if (getLength(listUserSend) > 0) { 84 | sendNotifications({ message: [-1, message], locale }, listUserSend.map(itm => itm.deviceId), data, listUserSend.map(itm => itm.id), '', image) 85 | } 86 | } 87 | 88 | export const sendNotiToAllUser = async (message, data, type, isLocale, image, header, role, isEnVi = true) => { 89 | let allUserEN = [] 90 | let allUserVI = [] 91 | 92 | if (!isEnVi || getLength(message.en) > 0) { 93 | allUserEN = await UserServices.getAllDeviceID('en', isLocale, role) 94 | } 95 | if (!isEnVi || getLength(message.vi) > 0) { 96 | allUserVI = await UserServices.getAllDeviceID('vi', isLocale, role) 97 | } 98 | 99 | if (getLength(allUserEN) > 0) { 100 | sendNotifications({ message: [type, isEnVi ? [message.en] : message], locale: 'en' }, allUserEN.map(itm => itm.deviceId), data, allUserEN.map(itm => itm.id), header ? header.en : '', image) 101 | } 102 | if (getLength(allUserVI) > 0) { 103 | sendNotifications({ message: [type, isEnVi ? [message.vi] : message], locale: 'vi' }, allUserVI.map(itm => itm.deviceId), data, allUserVI.map(itm => itm.id), header ? header.vi : '', image) 104 | } 105 | } 106 | 107 | /* 108 | Data message must contain 109 | { 110 | message, locale 111 | } 112 | */ 113 | export const sendNotifications = (dataMess, regTokens, data, userId, headings, image, soundName = 'notisound', isSilent = false) => { 114 | if (getLength(regTokens) > 0) { 115 | const dataNotification = { 116 | contents: { 117 | en: sendMessageFilter(dataMess.message, dataMess.locale) 118 | }, 119 | include_player_ids: typeof (regTokens) === 'string' ? [regTokens] : regTokens 120 | } 121 | 122 | if (headings) { 123 | dataNotification.headings = { en: headings } 124 | } 125 | // Add image to body 126 | if (image) { 127 | dataNotification.large_icon = image 128 | dataNotification.big_picture = image 129 | } 130 | const notification = new OneSignal.Notification(dataNotification) 131 | 132 | // Send data to client 133 | if (data) { 134 | notification.postBody.data = data 135 | } 136 | // Add icon app 137 | notification.postBody.small_icon = 'ic_launcher' 138 | 139 | // Add sound notification 140 | if (!isSilent) { 141 | notification.postBody.ios_sound = soundName + '.mp3' 142 | notification.postBody.android_sound = soundName 143 | } 144 | oneSignalClient.sendNotification(notification, function (err) { 145 | if (!err && getLength(userId) > 0) { 146 | const listUserID = typeof (userId) === 'string' ? [userId] : userId 147 | NotificationServices.createLocal({ type: dataMess.message[0], bonusValue: dataMess.message[1], image, listUserID }) 148 | logDebug('Notification send OK') 149 | } 150 | }) 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /controller/auth.js: -------------------------------------------------------------------------------- 1 | import BaseAPI from "."; 2 | import { User } from "../model"; 3 | import { 4 | fetchAPI, 5 | generateToken, 6 | genUpdate, 7 | lowerCase, 8 | calculateHash, 9 | } from "../common/function"; 10 | 11 | export default class AuthServices { 12 | static async login(req, res) { 13 | try { 14 | const { email, password } = req.body; 15 | const emailFormat = lowerCase(email); 16 | var resultLogin = await User.findOne({ email: emailFormat }); 17 | if (resultLogin == null) { 18 | res.status(404).send({ 19 | status: 404, 20 | data: resultLogin, 21 | msg: "Login Fail", 22 | error: "User Not Exists", 23 | }); 24 | } else { 25 | var hashPassword = calculateHash( 26 | emailFormat, 27 | password, 28 | resultLogin.nonce 29 | ); 30 | if (resultLogin.password == hashPassword) { 31 | const jwtToken = 32 | resultLogin == null ? "" : generateToken(emailFormat); 33 | res.status(200).send({ 34 | status: 200, 35 | token: jwtToken, 36 | data: resultLogin, 37 | msg: "Login Successful", 38 | error: 0, 39 | }); 40 | } else { 41 | res.status(401).send({ 42 | status: 401, 43 | data: "", 44 | msg: "Login Fail", 45 | error: "Wrong Password", 46 | }); 47 | } 48 | } 49 | } catch (error) { 50 | res.status(500).send("error :" + error); 51 | } 52 | } 53 | static async register(req, res) { 54 | try { 55 | const { email, password, isLogin } = req.body; 56 | var nonce = 0; 57 | var hashPassword = calculateHash(email, password, nonce); 58 | while (hashPassword.substring(0, 2) !== Array(3).join("0")) { 59 | nonce++; 60 | hashPassword = calculateHash(email, password, nonce); 61 | } 62 | res.json( 63 | await AuthServices.onCreateUser({ 64 | isLogin, 65 | email, 66 | password: hashPassword, 67 | nonce: nonce, 68 | }) 69 | ); 70 | } catch (error) { 71 | res.status(500).send("error :" + error); 72 | } 73 | } 74 | 75 | static async changePassword(req, res) { 76 | try { 77 | const { oldPassword, newPassword } = req.body; 78 | 79 | BaseAPI.authorizationAPI(req, res, async (createdUser) => { 80 | const result = await User.findOne({ 81 | email: createdUser, 82 | }); 83 | 84 | if (result == null) { 85 | res.status(404).send({ 86 | status: 404, 87 | data: resultLogin, 88 | msg: "User Not Exists", 89 | error: "User Not Exists", 90 | }); 91 | } else { 92 | var hashPassword = calculateHash(createdUser, oldPassword, result.nonce); 93 | if (result.password == hashPassword) { 94 | var nonce = 0; 95 | var newHashPassword = calculateHash( 96 | createdUser, newPassword, nonce 97 | ); 98 | while (newHashPassword.substring(0, 2) !== Array(3).join("0")) { 99 | nonce++; 100 | newHashPassword = calculateHash( 101 | createdUser, newPassword, nonce 102 | ); 103 | } 104 | 105 | var resultChange = await User.findOneAndUpdate( 106 | { 107 | email: createdUser, 108 | }, 109 | { password: newHashPassword, nonce: nonce }, 110 | { new: true }, (err) => console.log(err) 111 | ); 112 | res.status(200).send({ 113 | status: 200, 114 | data: resultChange, 115 | msg: "Change Successful", 116 | error: 0, 117 | }); 118 | } else { 119 | res.status(401).send({ 120 | status: 401, 121 | data: "", 122 | msg: "Change Fail!", 123 | error: "Wrong Password", 124 | }); 125 | } 126 | } 127 | // res.json(payload); 128 | }); 129 | } catch (error) { 130 | res.status(500).send("error :" + error); 131 | } 132 | } 133 | 134 | static async onCreateUser(response) { 135 | return new Promise(async (resolve, reject) => { 136 | const { id, picture, password, email, isLogin, isLoginAdmin } = response; 137 | const emailFormat = lowerCase(email); 138 | 139 | const oldUser = password 140 | ? await User.findOne({ id: emailFormat }) 141 | : await User.findOne({ id }); 142 | 143 | const jwtToken = generateToken(emailFormat); 144 | if (oldUser) { 145 | if (isLogin || isLoginAdmin) { 146 | if (oldUser.password !== password) { 147 | resolve({ errMess: "namePwNotFound" }); 148 | } else { 149 | if (isLoginAdmin) { 150 | if (oldUser.role === userRole.admin) { 151 | await User.findOneAndUpdate({ id }, { image: picture }); 152 | resolve(BaseAPI.verifyResult({ jwtToken, data: oldUser })); 153 | } else { 154 | resolve({ errMess: "notAdmin" }); 155 | } 156 | } else { 157 | await User.findOneAndUpdate({ id }, { image: picture }); 158 | resolve(BaseAPI.verifyResult({ jwtToken, data: oldUser })); 159 | } 160 | } 161 | } else { 162 | if (password) { 163 | resolve({ errMess: "userExisted" }); 164 | } else { 165 | await User.findOneAndUpdate({ id }, { image: picture }); 166 | resolve(BaseAPI.verifyResult({ jwtToken, data: oldUser })); 167 | } 168 | } 169 | } else { 170 | if (isLogin) { 171 | resolve({ errMess: "namePwNotFound" }); 172 | } else { 173 | const stateCreate = { 174 | id: password ? emailFormat : id, 175 | firstName: response.family_name, 176 | lastName: response.given_name, 177 | locale: response.locale, 178 | nonce: response.nonce, 179 | email: emailFormat, 180 | image: picture, 181 | }; 182 | 183 | if (password) { 184 | stateCreate.password = password; 185 | } 186 | const result = await User.create(stateCreate); 187 | resolve({ jwtToken, data: result }); 188 | } 189 | } 190 | }); 191 | } 192 | 193 | static async update(req, res) { 194 | BaseAPI.authorizationAPI(req, res, async () => { 195 | try { 196 | const { id } = req.body; 197 | const updateField = genUpdate(req.body, [ 198 | "fullName", 199 | "locale", 200 | "image", 201 | "email", 202 | "gender", 203 | "phone", 204 | "address", 205 | "status", 206 | ]); 207 | await User.findOneAndUpdate( 208 | { id }, 209 | updateField, 210 | { new: true }, 211 | (err, result) => { 212 | if (result || !err) { 213 | res.json(result); 214 | } else { 215 | res.json(false); 216 | } 217 | } 218 | ); 219 | } catch (error) { 220 | res.status(500).send("error :" + error); 221 | } 222 | }); 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /controller/user.js: -------------------------------------------------------------------------------- 1 | import BaseAPI from "."; 2 | import { User } from "../model"; 3 | import { 4 | fetchAPI, 5 | generateToken, 6 | convertPasswordHMAC256, 7 | genUpdate, 8 | lowerCase, 9 | calculateHash, 10 | } from "../common/function"; 11 | import FB from "fb"; 12 | import { userRole } from "../common/constants"; 13 | 14 | export default class UserServices { 15 | static async count(req, res) { 16 | BaseAPI.authorizationAPI(req, res, async () => { 17 | const payload = await User.countDocuments({}); 18 | res.json(payload); 19 | }); 20 | } 21 | 22 | static async get(req, res) { 23 | BaseAPI.authorizationAPI(req, res, async (createdUser) => { 24 | const payload = await User.find({ 25 | email: createdUser, 26 | }); 27 | res.json(payload); 28 | }); 29 | } 30 | 31 | static async getById(req, res) { 32 | BaseAPI.authorizationAPI(req, res, async (createdUser) => { 33 | const payload = await User.find({ 34 | id: req.params.id, 35 | createdUser: createdUser, 36 | }); 37 | res.json(payload); 38 | }); 39 | } 40 | 41 | static async checkUser(req, res) { 42 | BaseAPI.authorizationAPI(req, res, async () => { 43 | try { 44 | const { id } = req.params; 45 | const payload = await User.findOne({ id }); 46 | if (payload) { 47 | res.json(true); 48 | } else { 49 | res.json(false); 50 | } 51 | } catch (error) { 52 | res.status(500).send("error :" + error); 53 | } 54 | }); 55 | } 56 | 57 | static async checkuserLocal(id) { 58 | const payload = await User.findOne({ id }); 59 | return !!payload; 60 | } 61 | 62 | static async postLoginPassword(req, res) { 63 | try { 64 | const { email, password, isLogin } = req.body; 65 | var nonce = 0; 66 | var hashPassword = calculateHash(email, password, nonce); 67 | while (hashPassword.substring(0, 2) !== Array(3).join("0")) { 68 | nonce++; 69 | hashPassword = calculateHash(email, password, nonce); 70 | } 71 | res.json( 72 | await UserServices.onCreateUser({ 73 | isLogin, 74 | email, 75 | password: hashPassword, 76 | }) 77 | ); 78 | } catch (error) { 79 | res.status(500).send("error :" + error); 80 | } 81 | } 82 | 83 | static async postLoginFacebook(req, res) { 84 | try { 85 | const { token } = req.body; 86 | FB.api( 87 | "/me", 88 | { 89 | fields: ["id", "name", "email", "link", "picture.type(large)"], 90 | access_token: token, 91 | }, 92 | async (response) => { 93 | const { id, name, email, picture } = response; 94 | res.json( 95 | await UserServices.onCreateUser({ 96 | id, 97 | name, 98 | email, 99 | picture: 100 | picture && picture.data && picture.data.url 101 | ? picture.data.url 102 | : "", 103 | }) 104 | ); 105 | } 106 | ); 107 | } catch (error) { 108 | res.status(500).send("error :" + error); 109 | } 110 | } 111 | 112 | static async postLoginGoogle(req, res) { 113 | try { 114 | const { token } = req.body; 115 | const response = await fetchAPI( 116 | `https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=${token}` 117 | ); 118 | res.json(await UserServices.onCreateUser(response)); 119 | } catch (error) { 120 | res.status(500).send("error :" + error); 121 | } 122 | } 123 | 124 | static async loginPassword(req, res) { 125 | try { 126 | const { email, password } = req.body; 127 | const emailFormat = lowerCase(email); 128 | var resultLogin = await User.findOne({ email: emailFormat }); 129 | if (resultLogin == null) { 130 | res.status(401).send({ 131 | status: 401, 132 | data: resultLogin, 133 | msg: "Login Fail", 134 | error: "User Not Exists", 135 | }); 136 | } else { 137 | var hashPassword = calculateHash( 138 | emailFormat, 139 | password, 140 | resultLogin.nonce 141 | ); 142 | if (resultLogin.password == hashPassword) { 143 | const jwtToken = 144 | resultLogin == null ? "" : generateToken(emailFormat); 145 | res.status(200).send({ 146 | status: 200, 147 | token: jwtToken, 148 | data: resultLogin, 149 | msg: "Login Successful", 150 | error: 0, 151 | }); 152 | } else { 153 | res.status(401).send({ 154 | status: 401, 155 | data: "", 156 | msg: "Login Fail", 157 | error: "Wrong Password", 158 | }); 159 | } 160 | } 161 | } catch (error) { 162 | res.status(500).send("error :" + error); 163 | } 164 | } 165 | 166 | static async onCreateUser(response) { 167 | return new Promise(async (resolve, reject) => { 168 | const { 169 | id, 170 | picture, 171 | password, 172 | email, 173 | isLogin, 174 | isLoginAdmin, 175 | 176 | } = response; 177 | const emailFormat = lowerCase(email); 178 | 179 | const oldUser = password 180 | ? await User.findOne({ id: emailFormat }) 181 | : await User.findOne({ id }); 182 | 183 | const jwtToken = generateToken(emailFormat); 184 | if (oldUser) { 185 | if (isLogin || isLoginAdmin) { 186 | if (oldUser.password !== password) { 187 | resolve({ errMess: "namePwNotFound" }); 188 | } else { 189 | if (isLoginAdmin) { 190 | if (oldUser.role === userRole.admin) { 191 | await User.findOneAndUpdate({ id }, { image: picture }); 192 | resolve(BaseAPI.verifyResult({ jwtToken, data: oldUser })); 193 | } else { 194 | resolve({ errMess: "notAdmin" }); 195 | } 196 | } else { 197 | await User.findOneAndUpdate({ id }, { image: picture }); 198 | resolve(BaseAPI.verifyResult({ jwtToken, data: oldUser })); 199 | } 200 | } 201 | } else { 202 | if (password) { 203 | resolve({ errMess: "userExisted" }); 204 | } else { 205 | await User.findOneAndUpdate({ id }, { image: picture }); 206 | resolve(BaseAPI.verifyResult({ jwtToken, data: oldUser })); 207 | } 208 | } 209 | } else { 210 | if (isLogin) { 211 | resolve({ errMess: "namePwNotFound" }); 212 | } else { 213 | const stateCreate = { 214 | id: password ? emailFormat : id, 215 | firstName: response.family_name, 216 | lastName: response.given_name, 217 | locale: response.locale, 218 | nonce: response.nonce, 219 | email: emailFormat, 220 | image: picture, 221 | }; 222 | 223 | if (password) { 224 | stateCreate.password = password; 225 | } 226 | const result = await User.create(stateCreate); 227 | resolve({ jwtToken, data: result }); 228 | } 229 | } 230 | }); 231 | } 232 | 233 | static async update(req, res) { 234 | BaseAPI.authorizationAPI(req, res, async () => { 235 | try { 236 | const { id } = req.body; 237 | const updateField = genUpdate(req.body, [ 238 | "fullName", 239 | "locale", 240 | "image", 241 | "email", 242 | "gender", 243 | "phone", 244 | "address", 245 | "status", 246 | ]); 247 | await User.findOneAndUpdate( 248 | { id }, 249 | updateField, 250 | { new: true }, 251 | (err, result) => { 252 | if (result || !err) { 253 | res.json(result); 254 | } else { 255 | res.json(false); 256 | } 257 | } 258 | ); 259 | } catch (error) { 260 | res.status(500).send("error :" + error); 261 | } 262 | }); 263 | } 264 | 265 | static async delete(req, res) { 266 | BaseAPI.authorizationAPI(req, res, async () => { 267 | try { 268 | const { id, status } = req.body; 269 | await User.findOneAndUpdate( 270 | { id }, 271 | { status }, 272 | { new: true }, 273 | async (err, result) => { 274 | if (result || !err) { 275 | res.json(result); 276 | } else { 277 | res.json(false); 278 | } 279 | } 280 | ); 281 | } catch (error) { 282 | res.send("error :" + error); 283 | } 284 | }); 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /common/function.js: -------------------------------------------------------------------------------- 1 | import jwt from 'jsonwebtoken' 2 | import fetch from 'node-fetch' 3 | import moment from 'moment' 4 | import converter from 'hex2dec' 5 | import bigdecimal from 'bigdecimal' 6 | import crypto from 'crypto-js' 7 | import rp from 'request-promise' 8 | import { sendGridId, kudoType } from './constants' 9 | import { isNull, isUndefined } from 'util' 10 | import numeral from 'numbro' 11 | const Cron = require('cron-converter') 12 | const SHA256 = require("crypto-js/sha256") 13 | 14 | export const sendEmail = (to, data, locale = 'resetPassword') => { 15 | return new Promise(async (resolve, reject) => { 16 | const options = { 17 | method: 'POST', 18 | url: 'https://api.sendgrid.com/v3/mail/send', 19 | headers: 20 | { 21 | 'content-type': 'application/json', 22 | authorization: 'Bearer ' + process.env.SENDGRID_API_KEY 23 | }, 24 | body: 25 | { 26 | personalizations: 27 | [{ 28 | to: [{ email: to }], 29 | dynamic_template_data: data 30 | }], 31 | from: { email: 'ush.smarthome@gmail.com' }, 32 | template_id: sendGridId[locale] 33 | }, 34 | json: true 35 | } 36 | rp(options, async (error, response) => { 37 | const resJson = await response.toJSON() 38 | if (resJson.statusCode === 400) { 39 | reject(error) 40 | } else { 41 | resolve() 42 | } 43 | }) 44 | }) 45 | } 46 | 47 | export const getCronExpression = (arrExpression) => { 48 | const cronInstance = new Cron() 49 | return cronInstance.fromArray(arrExpression).toString() 50 | } 51 | 52 | export const calculateDiffDate = (date1 = new Date(), date2, type) => { 53 | const dateNow = moment(date1) 54 | const dateTxs = moment(date2) 55 | const payload = dateNow.diff(dateTxs, type) 56 | return payload 57 | } 58 | 59 | export const generateToken = (userSign) => { 60 | return jwt.sign({ id: userSign }, process.env.SECRET_TOKEN) 61 | } 62 | 63 | export const generateKeyDevice = (userSign) => { 64 | return jwt.sign({ id: userSign, device: true }, process.env.SECRET_TOKEN) 65 | } 66 | 67 | export const verifyToken = (token) => { 68 | return jwt.verify(token, process.env.SECRET_TOKEN, (err) => !err) 69 | } 70 | 71 | export const decodeToken = (token) => { 72 | const decodeString = jwt.decode(token) 73 | return decodeString ? decodeString.id : null 74 | } 75 | 76 | export const convertDateMoment = (date, type) => { 77 | const dateFormat = new Date(date) 78 | const strTime = moment(dateFormat).format(type) 79 | return strTime 80 | } 81 | 82 | export const convertPasswordHMAC256Old = (password) => { 83 | var hashPassword = crypto.HmacSHA256(password, 'coin98_token') 84 | var hexhash = crypto.enc.Hex.stringify(hashPassword) 85 | return hexhash 86 | } 87 | 88 | export const convertPasswordHMAC256 = (password) => { 89 | var hashPassword = crypto.HmacSHA256(password, process.env.SECRET_TOKEN) 90 | var hexhash = crypto.enc.Hex.stringify(hashPassword) 91 | return hexhash 92 | } 93 | 94 | export const convertPasswordHMAC256Security = (password) => { 95 | var hashPassword = crypto.HmacSHA256(password, '0xaeb0325a6789f597b4f7c2c4dcb36b1ba4232384ffaf7b24670b71dafc564cec') 96 | var hexhash = crypto.enc.Hex.stringify(hashPassword) 97 | return hexhash 98 | } 99 | 100 | export const calculateHash = (email, password, nonce) => { 101 | return SHA256(email + password + nonce).toString() 102 | } 103 | 104 | export const getLength = (value) => { 105 | return value ? value.length : 0 106 | } 107 | 108 | export const checkNameUserName = (value, subValue) => { 109 | return getLength(value) > 0 ? value : subValue 110 | } 111 | 112 | export const onlyUnique = (value, index, self) => { 113 | return self.indexOf(value) === index 114 | } 115 | 116 | export const lowerCase = (value) => { 117 | return value ? value.toLowerCase() : value 118 | } 119 | 120 | export const upperCase = (value) => { 121 | return value ? value.toUpperCase() : value 122 | } 123 | 124 | export const genUpdate = (data, arrValue) => { 125 | const genObject = {} 126 | arrValue.map(itm => { 127 | if (data[itm] !== undefined && data[itm] !== null) { 128 | genObject[itm] = data[itm] 129 | } 130 | }) 131 | return genObject 132 | } 133 | 134 | export const getTimeExpression = (arrDate) => { 135 | const result = arrDate.map(value => { 136 | return value.length > 0 ? value.join(',') + ' ' : '* ' 137 | }) 138 | return result.join('') 139 | } 140 | 141 | export const generateOTPCode = () => { 142 | let text = '' 143 | const possible = '0123456789' 144 | for (let i = 0; i < 4; i++) { 145 | text += possible.charAt(Math.floor(Math.random() * possible.length)) 146 | } 147 | return text 148 | } 149 | 150 | export const generateKudoName = (typeKudo) => { 151 | let subName = 'post' 152 | 153 | switch (typeKudo) { 154 | case kudoType.video: 155 | subName = 'video' 156 | break 157 | case kudoType.article: 158 | subName = 'article' 159 | break 160 | case kudoType.report: 161 | subName = 'report' 162 | break 163 | case kudoType.token: 164 | subName = 'token statistic' 165 | break 166 | } 167 | return subName 168 | } 169 | 170 | export const filterLink = (text) => { 171 | if (text && text.length > 0) { 172 | const regex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|])/ig 173 | regex.lastIndex = 0 174 | const matches = [] 175 | let regexResult 176 | while ((regexResult = regex.exec(text)) !== null) { 177 | matches.push(regexResult[0]) 178 | } 179 | return matches 180 | } 181 | } 182 | 183 | export const generateRefID = () => { 184 | let text = '' 185 | const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' 186 | for (let i = 0; i < 7; i++) { 187 | text += possible.charAt(Math.floor(Math.random() * possible.length)) 188 | } 189 | return 'C98' + text 190 | } 191 | 192 | export const generateDateFromTo = (isSameDay, item) => { 193 | return isSameDay 194 | ? convertDateMoment(item.dateStart, 'HH:mm') + ' - ' + convertDateMoment(item.dateEnd, 'HH:mm') + ' ' + convertDateMoment(item.dateStart, 'DD/MM/YYYY') 195 | : convertDateMoment(item.dateStart, 'HH:mm DD/MM/YYYY') + ' - ' + convertDateMoment(item.dateEnd, 'HH:mm DD/MM/YYYY') 196 | } 197 | 198 | export const generateID = () => { 199 | let text = '' 200 | const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' 201 | for (let i = 0; i < 16; i++) { 202 | text += possible.charAt(Math.floor(Math.random() * possible.length)) 203 | } 204 | return text 205 | } 206 | 207 | export const fetchAPI = async (apiurl, headers) => { 208 | try { 209 | const response = await fetch(apiurl, headers) 210 | const responJson = await response.json() 211 | return responJson 212 | } catch (error) { 213 | return false 214 | } 215 | } 216 | 217 | export const logDebug = (message) => { 218 | if (process.env.IS_DEV === 'true') { 219 | console.log(message) 220 | } 221 | } 222 | 223 | export const convertBalanceToWei = (strValue, iDecimal = 18) => { 224 | var multiplyNum = new bigdecimal.BigDecimal(Math.pow(10, iDecimal)) 225 | var convertValue = new bigdecimal.BigDecimal(String(strValue)) 226 | return multiplyNum.multiply(convertValue).toString().split('.')[0] 227 | } 228 | 229 | export const scientificToDecimal = (num) => { 230 | const sign = Math.sign(num) 231 | // if the number is in scientific notation remove it 232 | if (/\d+\.?\d*e[\+\-]*\d+/i.test(num)) { 233 | const zero = '0' 234 | const parts = String(num).toLowerCase().split('e') // split into coeff and exponent 235 | const e = parts.pop() // store the exponential part 236 | let l = Math.abs(e) // get the number of zeros 237 | const direction = e / l // use to determine the zeroes on the left or right 238 | const coeffArray = parts[0].split('.') 239 | 240 | if (direction === -1) { 241 | coeffArray[0] = Math.abs(coeffArray[0]) 242 | num = zero + '.' + new Array(l).join(zero) + coeffArray.join('') 243 | } else { 244 | const dec = coeffArray[1] 245 | if (dec) l = l - dec.length 246 | num = coeffArray.join('') + new Array(l + 1).join(zero) 247 | } 248 | } 249 | 250 | if (sign < 0) { 251 | num = -num 252 | } 253 | 254 | return num 255 | } 256 | 257 | export const convertWeiToBalance = (strValue, iDecimal = 18) => { 258 | var multiplyNum = new bigdecimal.BigDecimal(Math.pow(10, iDecimal)) 259 | var convertValue = new bigdecimal.BigDecimal(String(strValue)) 260 | return convertValue.divide(multiplyNum).toString() 261 | } 262 | 263 | export const generateDataToken = (amount = 0, address) => { 264 | const transferOpCode = '0xa9059cbb' 265 | const ABIValueToTransfer = zeroPadLeft(converter.decToHex(amount.toString().split('.')[0]).replace('0x', ''), 64) 266 | 267 | if (address) { 268 | const ethNakedAddress = address.toLowerCase().replace('0x', '') 269 | const ABIAddressTarget = zeroPadLeft(ethNakedAddress) 270 | return transferOpCode + ABIAddressTarget + ABIValueToTransfer 271 | } else { 272 | return transferOpCode + ABIValueToTransfer 273 | } 274 | } 275 | 276 | export const genAddressActive = (data) => { 277 | return getLength(data) > 0 ? data.find(itm => itm.isActive).address : '' 278 | } 279 | 280 | const zeroPadLeft = (text, length = 64) => { 281 | while (text.length < length) { 282 | text = '0' + text 283 | } 284 | return text 285 | } 286 | 287 | export const concatStringAdd = (array) => { 288 | let nameSignal = '' 289 | array.map((item, index) => { 290 | nameSignal += item 291 | if (index !== (array.length - 1)) { 292 | nameSignal += ', ' 293 | } 294 | }) 295 | return nameSignal 296 | } 297 | 298 | export const formatNumberBro = (number, mantissa = 4, isReturnNaN) => { 299 | if (number !== 'null' && !isNull(number) && !isNaN(number) && !isUndefined(number) && number !== 'NaN') { 300 | if (number.toString().length > 0) { 301 | return numeral(number.toString().replace(/\,/g, '')).format({ trimMantissa: true, thousandSeparated: true, mantissa }) 302 | } 303 | } 304 | return isReturnNaN ? 'NaN' : 0 305 | } 306 | 307 | export const isObject = (val) => { 308 | return typeof val === 'object' 309 | } 310 | --------------------------------------------------------------------------------