project init
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
dist/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
test/unit/coverage
|
||||
/.idea/
|
||||
npm-debug.*
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="TsLint" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,58 @@
|
||||
# node-loan-center
|
||||
|
||||
node服务中心
|
||||
|
||||
## 快速入门
|
||||
详细文档,参见 [egg 文档][eggjs], [midway 文档][midway]。
|
||||
|
||||
### 安装 启动
|
||||
|
||||
```bash
|
||||
$ yarn
|
||||
$ yarn dev
|
||||
$ open http://localhost:7001/
|
||||
```
|
||||
|
||||
### 部署
|
||||
|
||||
```bash
|
||||
$ npm start
|
||||
$ npm stop
|
||||
```
|
||||
|
||||
### 单元测试
|
||||
```
|
||||
yarn test
|
||||
|
||||
```
|
||||
- 具体参见 [midway 文档 - 单元测试](https://eggjs.org/zh-cn/core/unittest)。
|
||||
|
||||
### 目录结构
|
||||
```
|
||||
├─dist
|
||||
├─logs
|
||||
│ ├─ELKLog //上报kibana日志系统log
|
||||
| | ├─info.log
|
||||
| | └─error.log
|
||||
│ └─node-loan-center // 系统日志
|
||||
├─node_modules
|
||||
├─src //开发目录
|
||||
│ ├─app
|
||||
│ │ ├─controller
|
||||
│ │ ├─extend
|
||||
│ │ ├─helper
|
||||
│ │ ├─middleware
|
||||
│ │ └─public // 静态目录
|
||||
│ ├─config // 配置文件目录,包含test,prod,local等config文件
|
||||
│ ├─interface // ts接口目录
|
||||
│ ├─lib // 工具类目录,如基类
|
||||
│ └─service
|
||||
└─test // 单元测试用例目录
|
||||
└─app
|
||||
└─controller
|
||||
|
||||
```
|
||||
|
||||
[midway]: https://midwayjs.org
|
||||
[git-rules]: https://confluence.sui.work/pages/viewpage.action?pageId=51120607
|
||||
[eggjs]: https://eggjs.org/zh-cn/
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: '10'
|
||||
|
||||
install:
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
- npm i npminstall && node_modules\.bin\npminstall
|
||||
|
||||
test_script:
|
||||
- node --version
|
||||
- npm --version
|
||||
- npm run test
|
||||
|
||||
build: off
|
||||
Executable
+55
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "game-node-center",
|
||||
"version": "1.0.0",
|
||||
"description": "node服务中心",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"egg-cors": "^2.2.3",
|
||||
"egg-redis": "^2.4.0",
|
||||
"egg-scripts": "^2.10.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"midway": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^10.5.5",
|
||||
"cross-env": "^6.0.0",
|
||||
"egg-ci": "^1.8.0",
|
||||
"midway-bin": "1",
|
||||
"midway-mock": "1",
|
||||
"ts-node": "^8.3.0",
|
||||
"tslib": "^1.8.1",
|
||||
"tslint": "^5.11.0",
|
||||
"tslint-config-egg": "^1.0.0",
|
||||
"typescript": "^3.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.16.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "egg-scripts start --daemon --title=midway-server-node-loan-center --framework=midway --ts",
|
||||
"stop": "egg-scripts stop --title=midway-server-node-loan-center",
|
||||
"start_build": "npm run build && cross-env NODE_ENV=development midway-bin dev",
|
||||
"clean": "midway-bin clean",
|
||||
"dev": "cross-env NODE_ENV=local midway-bin dev --ts",
|
||||
"debug": "cross-env NODE_ENV=local midway-bin debug --ts",
|
||||
"test": "npm run lint && midway-bin test --ts",
|
||||
"cov": "midway-bin cov --ts",
|
||||
"lint": "tslint --fix -p tsconfig.json -t stylish",
|
||||
"ci": "npm run cov",
|
||||
"build": "midway-bin build -c"
|
||||
},
|
||||
"ci": {
|
||||
"version": "10"
|
||||
},
|
||||
"midway-bin-clean": [
|
||||
".vscode/.tsbuildinfo",
|
||||
"dist"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": ""
|
||||
},
|
||||
"author": "Cai",
|
||||
"license": "MIT"
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
import { Application } from 'egg';
|
||||
import * as path from 'path';
|
||||
import ElkTransport from './app/helper/logTransport';
|
||||
|
||||
export default (app: Application) => {
|
||||
app.beforeStart(async () => {});
|
||||
app.logger.set('remoteInfo', new ElkTransport({
|
||||
level: 'INFO',
|
||||
file: path.join(app.baseDir, '../logs/ELKLog/info.log'),
|
||||
}));
|
||||
app.logger.set('remoteError', new ElkTransport({
|
||||
level: 'ERROR',
|
||||
file: path.join(app.baseDir, '../logs/ELKLog/error.log'),
|
||||
}));
|
||||
};
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
import BaseController from "../../lib/baseController";
|
||||
import {controller, inject, post, provide} from "midway";
|
||||
import {IAccountService} from '../../interface/IAccountService'
|
||||
import {IAccountInfo} from "../../interface/IAccountInfo";
|
||||
|
||||
@provide()
|
||||
@controller('/node/user/')
|
||||
export class Account extends BaseController {
|
||||
|
||||
@inject('AccountService')
|
||||
service: IAccountService;
|
||||
|
||||
@post('/login')
|
||||
async login() {
|
||||
try {
|
||||
const accountInfo: IAccountInfo = {userAccount: 'cai', password: '123'};
|
||||
const result = await this.service.login(accountInfo);
|
||||
this.success(result)
|
||||
} catch (e) {
|
||||
this.fail(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
import { Context } from 'egg';
|
||||
|
||||
const LOG_COLLECTION = Symbol('Context#logCollection');
|
||||
export default {
|
||||
context: this,
|
||||
/**
|
||||
* 获取收集的日志信息
|
||||
* @returns {any}
|
||||
*/
|
||||
getLogs(this: Context) {
|
||||
const result: any = {};
|
||||
for (const [ k, val ] of this.logCollection) {
|
||||
result[k] = val;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* 收集日志信息
|
||||
* @param {string} key
|
||||
* @param {string} value
|
||||
*/
|
||||
setLogCollection(this: Context, key: string, value: string) {
|
||||
this.logCollection.set(key, value);
|
||||
},
|
||||
get logCollection(this: Context) {
|
||||
if (!this.context[LOG_COLLECTION]) {
|
||||
this.context[LOG_COLLECTION] = new Map();
|
||||
}
|
||||
return this.context[LOG_COLLECTION];
|
||||
},
|
||||
set logCollection(this: Context, value) {
|
||||
this.context[LOG_COLLECTION] = value;
|
||||
},
|
||||
};
|
||||
Executable
+92
@@ -0,0 +1,92 @@
|
||||
import { LoggerLevel, Context } from 'egg';
|
||||
import { FileBufferTransport } from 'egg-logger';
|
||||
import * as iconv from 'iconv-lite';
|
||||
import * as moment from 'moment';
|
||||
import * as os from 'os';
|
||||
import { OSLogField, BusinessLogField } from '../../interface/logInterface';
|
||||
|
||||
const { uid, username } = os.userInfo();
|
||||
|
||||
/**
|
||||
* 日志格式化
|
||||
*/
|
||||
class LogFormat extends Map {
|
||||
logField: BusinessLogField;
|
||||
osField: OSLogField;
|
||||
constructor() {
|
||||
super();
|
||||
this.osField = {
|
||||
pid: process.pid,
|
||||
nodeVersion: process.version,
|
||||
launchTime: moment().format('YYYY-MM-DD HH:mm:ss'),
|
||||
osUser: username,
|
||||
osUid: uid,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Log日志进行utf-8编码
|
||||
*/
|
||||
protected toBuffer() {
|
||||
const fields = { ...this.osField, ...this.logField };
|
||||
const str = JSON.stringify(fields) + '\n';
|
||||
return iconv.encode(str, 'utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化Log上下文
|
||||
* @param collect 日志对象
|
||||
* @param level 日志级别
|
||||
*/
|
||||
public formatFetchInfoMsg(collect: any, level: LoggerLevel) {
|
||||
this.logField = {
|
||||
fetchConsumeTime: 0,
|
||||
level: '',
|
||||
message: '',
|
||||
requestTime: '',
|
||||
stack: '',
|
||||
status: '',
|
||||
timestamp: '',
|
||||
total: 0,
|
||||
requestBody: {},
|
||||
method: '',
|
||||
url: '',
|
||||
};
|
||||
this.logField.timestamp = collect.startTime;
|
||||
this.logField.requestTime = moment(collect.startTime).format('YYYY-MM-DD HH:mm:ss');
|
||||
this.logField.status = collect.status;
|
||||
this.logField.message = collect.message;
|
||||
this.logField.stack = collect.stack;
|
||||
this.logField.level = collect.level || level;
|
||||
this.logField.url = collect.url;
|
||||
this.logField.total = collect.end - collect.start;
|
||||
if (collect.fetchStart && collect.fetchEnd) {
|
||||
this.logField.requestBody = collect.requestBody;
|
||||
this.logField.method = collect.method;
|
||||
this.logField.fetchConsumeTime = collect.fetchEnd - collect.fetchStart;
|
||||
}
|
||||
return this.toBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
export default class ElkTransport extends FileBufferTransport {
|
||||
|
||||
log(this: Context, level: LoggerLevel, args: any) {
|
||||
const logFormat = new LogFormat();
|
||||
const logInfo = args[0];
|
||||
let buf;
|
||||
if (!this._stream) {
|
||||
const err = new Error(`${this.options.file} log stream had been closed`);
|
||||
console.error(err.stack);
|
||||
return;
|
||||
}
|
||||
if (typeof logInfo === 'string') {
|
||||
buf = logFormat.formatFetchInfoMsg({ message: logInfo }, level);
|
||||
} else {
|
||||
buf = logFormat.formatFetchInfoMsg(logInfo, level);
|
||||
}
|
||||
if (buf.length) {
|
||||
this._write(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
import { Context, EggAppConfig } from 'egg';
|
||||
|
||||
/**
|
||||
* elk 日志拦截中间件
|
||||
* @description 接口请求拦截,进行日志上报,根据config的环境配置,设置日志收集,prod默认开启
|
||||
* @param {EggAppConfig["elkLogger"]} options config 配置项 elkLogger
|
||||
* @returns {any}
|
||||
*/
|
||||
export default function elkLogger(options: EggAppConfig['elkLogger']): any {
|
||||
return async (ctx: Context, next: () => Promise<any>) => {
|
||||
const { match, enable } = options;
|
||||
// 是否符合配置规则
|
||||
if (match(ctx) && enable) {
|
||||
ctx.setLogCollection('fetchStart', Date.now());
|
||||
ctx.setLogCollection('url', ctx.url);
|
||||
ctx.setLogCollection('requestBody', ctx.request.body);
|
||||
ctx.setLogCollection('message', `${ctx.request.method} ${ctx.url} info`);
|
||||
ctx.setLogCollection('level', 'INFO');
|
||||
await next();
|
||||
ctx.setLogCollection('status', ctx.res.statusCode);
|
||||
ctx.setLogCollection('fetchEnd', Date.now());
|
||||
ctx.logger.info(ctx.getLogs());
|
||||
}
|
||||
};
|
||||
}
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
import { Context } from 'egg';
|
||||
|
||||
/**
|
||||
* 404状态处理
|
||||
* @returns {any}
|
||||
*/
|
||||
export default function notFound(): any {
|
||||
return async (ctx: Context, next: () => Promise<any>) => {
|
||||
await next();
|
||||
if (ctx.status === 404 && !ctx.body) {
|
||||
if (ctx.acceptJSON) {
|
||||
ctx.body = {
|
||||
code: '404',
|
||||
data: {},
|
||||
msg: '页面坐火箭去了',
|
||||
};
|
||||
} else {
|
||||
ctx.body = '<h1>Page Not Found</h1>';
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
## public static file directory!
|
||||
Executable
+80
@@ -0,0 +1,80 @@
|
||||
import { EggAppConfig, EggAppInfo, PowerPartial, Context } from 'midway';
|
||||
|
||||
export type DefaultConfig = PowerPartial<EggAppConfig>;
|
||||
|
||||
export default (appInfo: EggAppInfo) => {
|
||||
const config = {} as DefaultConfig;
|
||||
|
||||
// use for cookie sign key, should change to your own and keep security
|
||||
config.keys = appInfo.name + '_{{keys}}';
|
||||
|
||||
// elk日志中间件,404处理中间件
|
||||
config.middleware = [ 'elkLogger', 'notFound' ];
|
||||
|
||||
// 合成配置
|
||||
const bizConfig = {
|
||||
sourceUrl: '',
|
||||
elkLogger: {
|
||||
// 请求url匹配规则
|
||||
match(ctx: Context) {
|
||||
const reg = /.*/;
|
||||
return reg.test(ctx.url);
|
||||
},
|
||||
// 是否启用
|
||||
enable: true,
|
||||
},
|
||||
};
|
||||
// 安全处理
|
||||
config.security = {
|
||||
csrf: {
|
||||
enable: false,
|
||||
},
|
||||
methodnoallow: {
|
||||
enable: false,
|
||||
},
|
||||
};
|
||||
// CORS 跨域处理
|
||||
config.cors = {
|
||||
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS',
|
||||
credentials: true,
|
||||
origin(ctx: Context) {
|
||||
const origin: string = ctx.get('origin');
|
||||
// 允许*.ssjlicai.com域名访问
|
||||
if (origin.indexOf('172.22.88.118') > -1) {
|
||||
console.log('come in');
|
||||
return origin;
|
||||
} else {
|
||||
return 'marketres.ssjlicai.com';
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// 日志配置
|
||||
config.logger = {
|
||||
outputJSON: false,
|
||||
appLogName: 'app.log',
|
||||
coreLogName: 'core.log',
|
||||
agentLogName: 'agent.log',
|
||||
errorLogName: 'error.log',
|
||||
};
|
||||
|
||||
// 业务接口domain
|
||||
config.apiDomain = {
|
||||
loanDomain: 'https://lcts3.ssjlicai.com',
|
||||
};
|
||||
|
||||
// redis
|
||||
config.redis = {
|
||||
client: {
|
||||
port: 6379, // Redis port
|
||||
host: '127.0.0.1', // Redis host
|
||||
password: '123456',
|
||||
db: 0,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
...bizConfig,
|
||||
...config,
|
||||
};
|
||||
};
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
export const development = {
|
||||
watchDirs: [
|
||||
'app',
|
||||
'lib',
|
||||
'service',
|
||||
'config',
|
||||
'app.ts',
|
||||
'agent.ts',
|
||||
'interface.ts',
|
||||
],
|
||||
overrideDefault: true,
|
||||
};
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
import { EggAppConfig, PowerPartial } from 'egg';
|
||||
import {Context} from "midway";
|
||||
|
||||
export default () => {
|
||||
const config: PowerPartial<EggAppConfig> = {};
|
||||
// 业务接口domain
|
||||
config.apiDomain = {
|
||||
loan: '',
|
||||
};
|
||||
// CORS 跨域处理
|
||||
config.cors = {
|
||||
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS',
|
||||
credentials: true,
|
||||
origin(ctx: Context) {
|
||||
const origin: string = ctx.get('origin');
|
||||
// 允许*.ssjlicai.com域名访问
|
||||
if (origin.indexOf('.ssjlicai.com') > -1) {
|
||||
return origin;
|
||||
} else {
|
||||
return 'marketres.ssjlicai.com';
|
||||
}
|
||||
},
|
||||
};
|
||||
return config;
|
||||
};
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
import { EggAppConfig, PowerPartial } from 'egg';
|
||||
|
||||
export default () => {
|
||||
const config: PowerPartial<EggAppConfig> = {};
|
||||
// 业务接口domain
|
||||
config.apiDomain = {
|
||||
loan: '',
|
||||
};
|
||||
return config;
|
||||
};
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
import { EggPlugin } from 'egg';
|
||||
|
||||
const plugin: EggPlugin = {
|
||||
static: true,
|
||||
cors: {
|
||||
enable: true,
|
||||
package: 'egg-cors',
|
||||
},
|
||||
redis: {
|
||||
enable: true,
|
||||
package: 'egg-redis',
|
||||
}
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
export interface IAccountInfo {
|
||||
userAccount: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
import {IAccountInfo} from "./IAccountInfo";
|
||||
import {ILoginResult} from "./ILoginResult";
|
||||
|
||||
export interface IAccountService {
|
||||
login(accountInfo: IAccountInfo): Promise<ILoginResult>;
|
||||
authUser(userInfo: IAccountInfo): boolean;
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
import { HttpMethod } from 'urllib';
|
||||
|
||||
/**
|
||||
* @description User-Service abstractions
|
||||
*/
|
||||
export interface IFetchOptions {
|
||||
method?: string;
|
||||
url: string;
|
||||
body: object;
|
||||
head?: object;
|
||||
timeout?: number;
|
||||
headers?: object;
|
||||
type?: HttpMethod;
|
||||
ssjToken: string;
|
||||
}
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
export interface ILoginResult {
|
||||
token:string
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
export enum ProductType {
|
||||
/**
|
||||
* 网贷(二部产品)
|
||||
*/
|
||||
WEB_LOAN,
|
||||
/**
|
||||
* 信用卡贷款(一部产品)
|
||||
*/
|
||||
CREDIT_CARD,
|
||||
}
|
||||
|
||||
export interface IRequestBody {
|
||||
head: any;
|
||||
body: any;
|
||||
}
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
export enum ResultCode {
|
||||
SUCCESS = '000000',
|
||||
FAILD = '100000',
|
||||
UNAUTH = '999999'
|
||||
}
|
||||
|
||||
export interface IResult {
|
||||
code: ResultCode;
|
||||
data: any;
|
||||
message: string;
|
||||
}
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
import { inject, Context } from 'midway';
|
||||
import { IRequestBody } from '../interface/IRequestBody';
|
||||
import {IResult, ResultCode} from "../interface/IResult";
|
||||
|
||||
export default class BaseController {
|
||||
|
||||
@inject()
|
||||
protected ctx: Context;
|
||||
|
||||
/**
|
||||
* 获取请求内容
|
||||
* @returns {IRequestBody}
|
||||
*/
|
||||
public getRequestBody(): IRequestBody {
|
||||
let params: IRequestBody;
|
||||
params = this.ctx.request.body.params && JSON.parse(this.ctx.request.body.params) || {};
|
||||
console.log(this.ctx.request.body, 'params');
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败回调封装
|
||||
* @param {Object} data
|
||||
*/
|
||||
public success(data: any) {
|
||||
const result: IResult = {
|
||||
code: ResultCode.SUCCESS,
|
||||
data: data,
|
||||
message: ''
|
||||
}
|
||||
this.ctx.body = result
|
||||
}
|
||||
/**
|
||||
* 错误回调封装
|
||||
* @param {string} message
|
||||
*/
|
||||
public fail(message: string) {
|
||||
const result: IResult = {
|
||||
code: ResultCode.FAILD,
|
||||
data: {},
|
||||
message
|
||||
};
|
||||
this.ctx.body = result
|
||||
}
|
||||
}
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
import { Context } from 'egg';
|
||||
import { IFetchOptions } from '../interface/IFetchOptions';
|
||||
import { inject, config } from 'midway';
|
||||
|
||||
export default class BaseService {
|
||||
@inject()
|
||||
protected ctx: Context;
|
||||
|
||||
@config('apiDomain')
|
||||
protected config: any;
|
||||
|
||||
/**
|
||||
* 处理请求
|
||||
* @param {IFetchOptions} option
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
public async fetch(option: IFetchOptions) {
|
||||
try {
|
||||
const data = {
|
||||
head: { ...option.head },
|
||||
body: { ...option.body },
|
||||
};
|
||||
// 用户登录标识
|
||||
const headers = {
|
||||
Authorization: `Bearer ${option.ssjToken}`,
|
||||
};
|
||||
const ajaxUrl = this.config.loanDomain + option.url;
|
||||
// 发起服务请求
|
||||
const result = await this.ctx.curl(ajaxUrl, {
|
||||
data,
|
||||
type: option.type || 'POST',
|
||||
headers,
|
||||
dataType: 'json',
|
||||
});
|
||||
// 接口请求失败日志上报
|
||||
if (result.status !== 200) {
|
||||
this.ctx.logger.error(this.ctx.getLogs());
|
||||
}
|
||||
return result.data;
|
||||
} catch (e) {
|
||||
this.ctx.logger.error(this.ctx.getLogs());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
import BaseService from '../lib/baseService';
|
||||
import {Context, inject, provide, Application} from "midway";
|
||||
import {IAccountInfo} from "../interface/IAccountInfo";
|
||||
import {IAccountService} from "../interface/IAccountService";
|
||||
import { sign } from 'jsonwebtoken';
|
||||
import {ILoginResult} from "../interface/ILoginResult";
|
||||
|
||||
@provide('AccountService')
|
||||
export class AccountService extends BaseService implements IAccountService{
|
||||
|
||||
@inject()
|
||||
app: Application;
|
||||
|
||||
@inject()
|
||||
ctx: Context;
|
||||
|
||||
salt: 'test123';
|
||||
|
||||
public login(accountInfo: IAccountInfo): Promise<ILoginResult> {
|
||||
return new Promise( async (resolve,reject) => {
|
||||
try {
|
||||
// 校验是否登录
|
||||
let token = await this.isLogin(accountInfo);
|
||||
if(!token) {
|
||||
// 校验用户信息
|
||||
const isAuth = await this.authUser(accountInfo)
|
||||
if(isAuth){
|
||||
token = await this.setToken(accountInfo)
|
||||
} else {
|
||||
token = ''
|
||||
}
|
||||
}
|
||||
const result:ILoginResult = { token }
|
||||
resolve(result)
|
||||
} catch (e) {
|
||||
reject('auth error');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private async isLogin(accountInfo: IAccountInfo): Promise<string> {
|
||||
try {
|
||||
const token: string = await this.getToken(accountInfo.userAccount)
|
||||
return token
|
||||
} catch (e) {
|
||||
throw 'isLogin error'
|
||||
}
|
||||
}
|
||||
|
||||
public async authUser(accountInfo: IAccountInfo) {
|
||||
return accountInfo.userAccount === 'cai' && accountInfo.password === '123'
|
||||
}
|
||||
private async setToken(accountInfo: IAccountInfo) {
|
||||
try {
|
||||
let token = sign({userName: accountInfo.userAccount}, this.salt);
|
||||
await this.app.redis.set(accountInfo.userAccount, token)
|
||||
return token
|
||||
} catch (e) {
|
||||
throw `redis error: ${e.msg}`
|
||||
}
|
||||
}
|
||||
|
||||
private getToken(userAccount: string) {
|
||||
let token = this.app.redis.get(userAccount);
|
||||
console.log('token', token)
|
||||
return token
|
||||
}
|
||||
}
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
/* tslint:disable */
|
||||
const { app, assert } = require('midway-mock/bootstrap');
|
||||
|
||||
/* tslint:enable */
|
||||
|
||||
describe('test/app/controller/home.test.ts', () => {
|
||||
|
||||
it('should assert', async () => {
|
||||
const pkg = require('../../../package.json');
|
||||
assert(app.config.keys.startsWith(pkg.name));
|
||||
// const ctx = app.mockContext({});
|
||||
// await ctx.service.xx();
|
||||
});
|
||||
|
||||
it('should POST /ocrAuth', () => {
|
||||
/* tslint:disable */
|
||||
return app.httpRequest().
|
||||
post('/node/ocrAuth').
|
||||
set('Authorization', 'Bearer ad7bc5ae-e19e-4d39-9a93-aa75bc01ede1').
|
||||
send({
|
||||
'params': JSON.stringify({
|
||||
'head': {
|
||||
'clientId': 0,
|
||||
'appUDID': '',
|
||||
'appVersion': '',
|
||||
'channelId': '',
|
||||
'innerMedia': '',
|
||||
'outerMedia': '',
|
||||
'subClientId': '0',
|
||||
'systemVersion': 'undefined',
|
||||
'origin': '',
|
||||
},
|
||||
'body': {
|
||||
'name': '蔡建帮',
|
||||
'address': '测试',
|
||||
'authOrg': '测试政府',
|
||||
'gender': '男',
|
||||
'idNo': '445222198911111111',
|
||||
'nation': '中国',
|
||||
'validDate': '20190909 - 20990907',
|
||||
'frontImage': '',
|
||||
'backImage': '',
|
||||
'productId': 'L0003',
|
||||
'channelType': 1,
|
||||
},
|
||||
}),
|
||||
}).
|
||||
expect(200);
|
||||
});
|
||||
});
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"compileOnSave": true,
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"inlineSourceMap": true,
|
||||
"module": "commonjs",
|
||||
"newLine": "lf",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUnusedLocals": true,
|
||||
"outDir": "dist",
|
||||
"pretty": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"stripInternal": true,
|
||||
"target": "ES2018"
|
||||
},
|
||||
"exclude": [
|
||||
"app/public",
|
||||
"app/views",
|
||||
"dist",
|
||||
"node_modules*",
|
||||
"test",
|
||||
"**/*.d.ts",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": ["tslint-config-egg"],
|
||||
"rules": {
|
||||
"linebreak-style": [ true, "CRLF" ]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user