Commit 400b5854 authored by ml's avatar ml

日志审计、Madex用户管理相关

parent c136b23b
// 配置文件暂时和 js 的导出方式保持一致,涉及到线上环境变量的替换等
module.exports = {
BASE_URL: "/backend/v1/"
BASE_URL: "/backend/v1/",
OSS_CONFIG: {
region: "oss-cn-hongkong",
accessKeyId: "LTAIKTww9T29bp9t",
accessKeySecret: "6cbKA6dlkg2BIHovQV217izCrwJg8B",
endPoint: "https://oss-cn-hongkong.aliyuncs.com",
avatar_bucket: "biiigle-oss-bucket-oss",
linkcoin_host: "https://res.linkcoin.pro",
kyc_bucket: "bibox-oss",
bibox_host: "https://res.bibox.com"
}
};
\ No newline at end of file
This diff is collapsed.
......@@ -76,6 +76,7 @@
"sequelize": "^4.44.4",
"should": "^12.0.0",
"tunnel": "^0.0.6",
"uuid": "9.0.1"
"uuid": "9.0.1",
"image-size": "1.0.2"
}
}
export const EMAIL_FORBID_TEMPLATE = "MODIFYING_MAILBOX_FORBID_FUNCTION"; // 限制用户3个功能
export const AFTER_MODIFIED_MAILBOX_TIP = "AFTER_MODIFIED_MAILBOX_TIP"; // 7天每日提醒
export const REAL_NAME_PASS = "REAL_NAME_PASS"; // 实名认证通过
export const REAL_NAME_DENY = "REAL_NAME_DENY"; // 实名认证未通过
\ No newline at end of file
export const ErrorCode = {
PARAM_MISS:'30000',//请求参数错误
DATA_NOT_EXIST:'30001',//数据不存在
DATA_EXIST:'30002',//数据已存在
export const ErrorCode = {
PARAM_MISS: '30000',//请求参数错误
DATA_NOT_EXIST: '30001',//数据不存在
DATA_EXIST: '30002',//数据已存在
NOT_LOGIN: '30003',//账号未登录
NO_PERMISSION: '30004',//账号没有权限
USER_EXIST: '30005',//用户已存在
......@@ -24,6 +24,15 @@ export const ErrorCode = {
TOTP_KEY_OVERSTAYED: '30022',//密钥已失效,请重新获取
USER_TYPE_ILLEGAL: '30023',//用户类型不合法
NEED_INPUT_GOOGLE_CODE: '30024',//请输入Google验证码
PUSH_NOT_UPDATE: '30025',//已经推送不允许修改
PUSH_NOT_UPDATE: '30025',//已经推送不允许修改
UID_LIMIT: '30026',//UID受限,不允许操作
UPDATE_EMAIL_EXIST: '30027',//要修改的邮箱已存在
EMAIL_USED_NTO_CHANGE: '30028',//该邮箱已经使用,请切换邮箱
EMAIL_CHANGE_OFTEN: '30029',//请勿频繁切换邮箱
DAD_ACCOUNT_NOT_EXIST: '30030',//该子账户的父账户不存在
DEL_USER_NO_UNLOCK: '30031',//删除的用户不予许解锁
USER_NOT_LOCK: '30032',//该用户未锁定
REASON_TOO_LONG: '30033',//驳回原因过长
DATA_STATUS_CHANGED: '30034',//非法操作,数据状态已经变更
}
export const KYC_STATUS = {
STATUS_NOT_COMMIT: 0,//未提交
STATUS_AUDITING: 1,//审核中
STATUS_AUDIT_DENY: 2,//审核不通过
STATUS_AUDIT_PASS: 3//审核通过
}
export const SETTING_FLAG = {
FLAG_REAL_NAME_AUTH: 1 << 4
}
\ No newline at end of file
export const MUserRedisKey = {
//登陆限制
USER_LOCK_SUFFIX :".login_lock"
}
\ No newline at end of file
import * as mUserManageService from "../service/mUserManage.service";
import { QueryVO } from "../service/mUserManage.service";
let { logger, Res3Utils, optionalUtils: Optional, apiAssertUtils: ApiAssert } = require('@madex/ex-js-public');
import { ErrorCode } from "../../../constant/errorCode";
import { getCurrentUserId, isAdminUserBySessionId } from "../../../utils/aclUserUtils";
import * as IsEmail from "isemail";
import { isLimitUserId } from "../../../utils/mUserCommonUtils";
let isIp = require('is-ip');
/**
* Madex 用户列表
* @param req
* @param infoVO
*/
export const userList = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserManageCtrl.userList";
try {
queryVO.page = Optional.opt(queryVO, 'page', 1);
queryVO.size = Optional.opt(queryVO, 'size', 20);
let res = await mUserManageService.userList(queryVO);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
/**
* Madex 单个用户详情
* @param req
* @param queryVO
*/
export const oneUserDetail = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserManageCtrl.oneUserDetail";
try {
if (!queryVO.user_id) {
throw ErrorCode.PARAM_MISS
}
let res = await mUserManageService.oneUserDetail(queryVO.user_id);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
/**
* Madex 修改用户邮箱
* @param req
* @param queryVO
*/
export const updateUserEmail = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserManageCtrl.updateUserEmail";
try {
if (!queryVO.user_id || !queryVO.email || !queryVO.totp_code) {
throw ErrorCode.PARAM_MISS
}
//超管才有权限修改
await isAdminUserBySessionId(req.cookies.session_id);
//uid 是否在受限范围内
if (isLimitUserId(queryVO.user_id)) {
throw ErrorCode.UID_LIMIT
}
if (!IsEmail.validate(queryVO.email, { minDomainAtoms: 2 })) {
//邮箱格式错误
throw '2000';
}
let ip = isIp(req.ip) ? req.ip : '*.*.*.*';
let currentUserId = await getCurrentUserId(req.cookies.session_id);
let res = await mUserManageService.updateUserEmail(currentUserId, queryVO.user_id, queryVO.email, queryVO.totp_code, ip);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
/**
* Madex 锁定账户
* @param req
* @param queryVO
*/
//TODO: 前端需要弹窗选择锁定当前账户 还是 当前账户及其所有子账户
export const lockAccount = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserManageCtrl.lockAccount";
try {
if (!queryVO.user_id || !queryVO.lock_type || !queryVO.totp_code) {
throw ErrorCode.PARAM_MISS
}
//超管才有权限
await isAdminUserBySessionId(req.cookies.session_id);
//uid 是否在受限范围内
if (isLimitUserId(queryVO.user_id)) {
throw ErrorCode.UID_LIMIT
}
let ip = isIp(req.ip) ? req.ip : '*.*.*.*';
let currentUserId = await getCurrentUserId(req.cookies.session_id);
let res = await mUserManageService.lockAccount(currentUserId, queryVO.user_id, ip, queryVO.lock_type, queryVO.totp_code);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
/**
* 解锁账户
* @param req
* @param queryVO
*/
//TODO: 前端需要弹窗选择锁定当前账户 还是 当前账户及其所有子账户
export const unlockAccount = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserManageCtrl.unlockAccount";
try {
if (!queryVO.user_id || !queryVO.lock_type || !queryVO.totp_code) {
throw ErrorCode.PARAM_MISS
}
//超管才有权限
await isAdminUserBySessionId(req.cookies.session_id);
//uid 是否在受限范围内
if (isLimitUserId(queryVO.user_id)) {
throw ErrorCode.UID_LIMIT
}
let ip = isIp(req.ip) ? req.ip : '*.*.*.*';
let currentUserId = await getCurrentUserId(req.cookies.session_id);
let res = await mUserManageService.unlockAccount(currentUserId, queryVO.user_id, ip, queryVO.lock_type, queryVO.totp_code);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
/**
* Madex 清除登陆限制
* @param req
* @param queryVO
*/
export const clearLoginLimit = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserManageCtrl.clearLoginLimit";
try {
if (!queryVO.user_id || !queryVO.totp_code) {
throw ErrorCode.PARAM_MISS
}
//超管才有权限
await isAdminUserBySessionId(req.cookies.session_id);
//uid 是否在受限范围内
if (isLimitUserId(queryVO.user_id)) {
throw ErrorCode.UID_LIMIT
}
let ip = isIp(req.ip) ? req.ip : '*.*.*.*';
let currentUserId = await getCurrentUserId(req.cookies.session_id);
let res = await mUserManageService.clearLoginLimit(currentUserId, queryVO.user_id, ip, queryVO.totp_code);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
/**
* Madex 清除24小时提现限制
* @param req
* @param queryVO
*/
export const clear24WithdrawLimit = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserManageCtrl.clear24WithdrawLimit";
try {
if (!queryVO.user_id || !queryVO.totp_code) {
throw ErrorCode.PARAM_MISS
}
//超管才有权限
await isAdminUserBySessionId(req.cookies.session_id);
//uid 是否在受限范围内
if (isLimitUserId(queryVO.user_id)) {
throw ErrorCode.UID_LIMIT
}
let ip = isIp(req.ip) ? req.ip : '*.*.*.*';
let currentUserId = await getCurrentUserId(req.cookies.session_id);
let res = await mUserManageService.clear24WithdrawLimit(currentUserId, queryVO.user_id, ip, queryVO.totp_code);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
import * as mUserOptLogService from "../service/mUserOptLog.service";
import { QueryVO } from "../service/mUserOptLog.service";
let { logger, Res3Utils, optionalUtils: Optional, apiAssertUtils: ApiAssert } = require('@madex/ex-js-public');
import { ErrorCode } from "../../../constant/errorCode";
/**
* Madex 用户操作日志列表
* @param req
* @param infoVO
*/
export const list = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserOptLogCtrl.list";
try {
queryVO.page = Optional.opt(queryVO, 'page', 1);
queryVO.size = Optional.opt(queryVO, 'size', 20);
let res = await mUserOptLogService.list(queryVO);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
import * as mUserRealNameService from "../service/mUserRealName.service";
import { QueryVO } from "../service/mUserRealName.service";
let { logger, Res3Utils, optionalUtils: Optional, apiAssertUtils: ApiAssert } = require('@madex/ex-js-public');
import { ErrorCode } from "../../../constant/errorCode";
import { getCurrentUserId, getOneAclUserByUid, isAdminUserBySessionId } from "../../../utils/aclUserUtils";
import { isLimitUserId } from "../../../utils/mUserCommonUtils";
import { AclUserInfoConst } from "../../../constant/aclUserConstant";
let isIp = require('is-ip');
/**
* Madex 用户实名列表
* @param req
* @param infoVO
*/
export const kycList = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserRealNameCtrl.kycList";
try {
queryVO.page = Optional.opt(queryVO, 'page', 1);
queryVO.size = Optional.opt(queryVO, 'size', 20);
let currentUserId = await getCurrentUserId(req.cookies.session_id);
let dbInfo = await getOneAclUserByUid(currentUserId);
let isAdmin = dbInfo.user_type == AclUserInfoConst.USER_TYPE.ADMIN
let res = await mUserRealNameService.kycList(queryVO, isAdmin);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
/**
* Madex 单个实名用户详情
* @param req
* @param queryVO
*/
export const oneDetail = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserRealNameCtrl.oneDetail";
try {
if (!queryVO.id) {
throw ErrorCode.PARAM_MISS
}
//超管才有权限修改
await isAdminUserBySessionId(req.cookies.session_id);
let res = await mUserRealNameService.oneDetail(queryVO.id);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
/**
* Madex 实名审核
* @param req
* @param queryVO
*/
export const audit = async (req: any, queryVO: QueryVO) => {
let func_name = "mUserRealNameCtrl.audit";
try {
if (!queryVO.id) {
throw ErrorCode.PARAM_MISS
}
//超管才有权限修改
await isAdminUserBySessionId(req.cookies.session_id);
let currentUserId = await getCurrentUserId(req.cookies.session_id);
let ip = isIp(req.ip) ? req.ip : '*.*.*.*';
let res = await mUserRealNameService.audit(queryVO, currentUserId, ip);
return Res3Utils.result(res);
}
catch (e) {
logger.error(`${func_name} error:${e}`);
return Res3Utils.getErrorResult(e);
}
};
import { ormDB, userInfo, userAccountChangeLog } from "@madex/ex-ts-dao";
export const existEmail = async function (email: string) {
let where = {
type: 1,//邮箱
[ormDB.Op.or]: {
account_old: email,
account_new: email
}
}
let dbInfo = await userAccountChangeLog.prototype.findOne({
where: where,
raw: true
});
return dbInfo
}
export const getProcessingEmailListByMUserId = async function (m_user_id: number) {
let where = {
type: 1,//邮箱,
user_id: m_user_id,
state: 3//状态 3 修改完成--可在7日内恢复成5
}
let dbInfoList = await userAccountChangeLog.prototype.findAll({
where: where,
raw: true
});
return dbInfoList
}
import { ormDB, userInfo, userAccountOperateLog, aclUserInfo } from "@madex/ex-ts-dao";
export const TYPE = {
//google密钥
GOOGLE_KEY: 0,
//2小时限制
TWO_HOUR_LIMIT: 1,
//24小时限制
TWENTY_FOUR_HOUR_LIMIT: 2,
//邮箱
MAIL: 3,
//最大提现额度
MAXIMUM_WITHDRAWAL_AMOUNT: 4,
//账户状态
ACCOUNT_STATUS: 5,
//能否提现修改
CAN_WITHDRAW_AND_MODIFY: 6,
//账户激活状态
ACCOUNT_ACTIVATION_STATUS: 7,
//备注
REMARK: 8,
//实名
KYC: 9
}
export const recordOperateLog = async function (m_user_id: number, operate_user_id: number, operate_type: number,
comment: string, before_v: string, after_v: string) {
let aclUser = await aclUserInfo.prototype.findOne({
where: {
user_id: operate_user_id
}
});
let operate_user_name = aclUser.account ? aclUser.account : operate_user_id;
await userAccountOperateLog.prototype.create({
user_id: m_user_id,
operate_user_id: operate_user_id,
operate_user_name: operate_user_name,
operate_type: operate_type,
operational_situation: comment,
before_value: before_v,
after_value: after_v,
createdAt: new Date(),
updatedAt: new Date()
});
}
\ No newline at end of file
import { ormDB, userInfoSon } from "@madex/ex-ts-dao";
let _ = require('lodash');
export async function getFatherUserId(user_id: number | any) {
let dbInfo = await userInfoSon.prototype.findOne({
where: {
user_id: user_id
},
raw: true
});
return dbInfo ? dbInfo.father_id : null
}
export async function getUidsByFatherUid(father_user_id: number) {
let dbInfoList = await userInfoSon.prototype.findAll({
where: {
father_id: father_user_id
},
raw: true
});
return dbInfoList.length ? dbInfoList.map(item => item.user_id) : []
}
This diff is collapsed.
import { ormDB, userLog, userProfile } from "@madex/ex-ts-dao";
import { ErrorCode } from "../../../constant/errorCode";
import { getProfileByUserIds } from "./mUserProfile.service";
let _ = require('lodash');
let { logger, datetimeUtils } = require('@madex/ex-js-public');
export const MUserLogType = {
UP_EMAIL: 25,//运营修改用户邮箱
}
export interface QueryVO {
page?: number,
size?: number
user_id?: number | any;
place?: string | any;
type?: number;
start_date?: Date | any;
end_date?: Date | any;
}
export async function list(queryVO: QueryVO) {
let where = Object.create(null);
if (queryVO.user_id) {
where.user_id = queryVO.user_id;
}
if (queryVO.type) {
where.type = queryVO.type;
}
if (queryVO.start_date && queryVO.end_date) {
let from = datetimeUtils.trim(queryVO.start_date, 's');
let to = datetimeUtils.trim(queryVO.end_date, 's');
where.createdAt = { [ormDB.Op.between]: [from, to] };
}
let resList = await userLog.prototype.findAndCount({
where: where,
limit: queryVO.size,
offset: (Number(queryVO.page) - 1) * Number(queryVO.size),
order: [["id", "desc"]],
raw: true
});
if (resList.rows.length > 0) {
let uids = resList.rows.map(item => item.user_id);
let profileMap = await getProfileByUserIds(_.uniq(uids));
for (let item of resList.rows) {
let oneProfileInfo = profileMap[item.user_id];
item.nick_name = oneProfileInfo ? (oneProfileInfo.nick_name ? oneProfileInfo.nick_name : "") : "";
}
}
return resList;
}
export const addLog = async function (m_user_id: number, type: number, ip: string, operator: number, comment: string) {
userLog.prototype.create({
user_id: m_user_id,
type: type,
user_ip: ip,
device_id: operator,
comment: comment,
createdAt: new Date(),
updatedAt: new Date(),
})
}
import { ormDB, userProfile } from "@madex/ex-ts-dao";
let _ = require('lodash');
export async function getProfileByUserId(user_id: number | any) {
let dbInfo = await userProfile.prototype.findOne({
where: {
user_id: user_id
},
raw: true
});
return dbInfo ? dbInfo : null
}
export async function getProfileByUserIds(userIds: number[]) {
let dbInfoList = await userProfile.prototype.findAll({
where: {
user_id: { [ormDB.Op.in]: userIds }
},
raw: true
});
let resMap = {};
for (let item of dbInfoList) {
resMap[item.user_id] = item
}
return resMap;
}
This diff is collapsed.
......@@ -12,6 +12,12 @@ export const LogType = {
DEL: 4,//删除
TOTP: 5,//谷歌
SAVE: 6,//保存(添加或修改)
UPDATE_MUSER_EMAIL: 7,//修改 Madex 用户邮箱
LOCK_MUSER: 8,//锁定用户
UNLOCK_MUSER: 9,//解锁用户
CLEAR_LOGIN_LIMIT: 10,//清除用户登陆限制
WITHDRAW_24_LIMIT: 11,//清除用户24小时限制
KYC_AUDIT: 12,//用户实名认证审核
}
export const addOptLog = async function (user_id: any, msg: any, type: any, fail_reason?: any, session_id?: any) {
......
......@@ -20,16 +20,19 @@ import * as ReqUtils from "../../../utils/req-utils";
import * as spotPairCtrl from "../../mvc/control/spotPair.control";
import * as coinTypeCtrl from "../../mvc/control/coinType.control";
import * as noticeCtrl from "../../mvc/control/notice.control";
import * as mUserOptLogCtrl from "../../mvc/control/mUserOptLog.control";
import * as mUserManageCtrl from "../../mvc/control/mUserManage.control";
import * as mUserRealNameCtrl from "../../mvc/control/mUserRealName.control";
const getFunc = {
'user/info': userController.getUserInfo,
};
const postFunc = {
//国际化
'i18n/info/list': i18nCtrl.list,
'i18n/info/add': i18nCtrl.add,
'i18n/info/update': i18nCtrl.update,
'i18n/info/del': i18nCtrl.del,
'i18n/info/log/list': i18nLogCtrl.list,
'i18n/info/log/revert': i18nLogCtrl.revert,
......@@ -38,12 +41,12 @@ const postFunc = {
'coinType/add': coinTypeCtrl.add,
'coinType/list': coinTypeCtrl.list,
//权限管理
'acl/user/add': aclUserCtrl.add,
'acl/user/list': aclUserCtrl.list,
'acl/user/update': aclUserCtrl.update,
'acl/user/updateStatus': aclUserCtrl.updateStatus,
'acl/user/resetPwd': aclUserCtrl.resetPwd,
'acl/auth/list': aclRoleAuthCtrl.authList,
'acl/auth/tree': aclRoleAuthCtrl.getAuthTree,
'acl/auth/getByUser': aclRoleAuthCtrl.getAuthByUser,
......@@ -51,16 +54,17 @@ const postFunc = {
'acl/auth/save': aclRoleAuthCtrl.saveAuth,
'acl/auth/del': aclRoleAuthCtrl.delAuth,
//角色管理
'acl/role/list': aclRoleAuthCtrl.roleList,
'acl/role/getByUser': aclRoleAuthCtrl.getRoleByUser,
//'acl/role/getUserList':aclUserCtrl.list,
'acl/role/getAll': aclRoleAuthCtrl.getAllRole,
'acl/role/save': aclRoleAuthCtrl.saveRole,
'acl/role/del': aclRoleAuthCtrl.delRole,
'acl/changeRoleAuth': aclRoleAuthCtrl.changeRoleAuth,
'acl/changeUserRole': aclRoleAuthCtrl.changeUserRole,
//管理后台用户管理
'user/getInfo': userOptCtrl.getInfo,
'user/login': userOptCtrl.login,
'user/logout': userOptCtrl.logout,
......@@ -68,21 +72,36 @@ const postFunc = {
'user/updatePwd': userOptCtrl.updatePwd,
'user/bind/totp/ask': userOptCtrl.bindTotpAsk,
'user/bind/totp/confirm': userOptCtrl.bindTotpConfirm,
'user/auth/config/list': userAuthConfigCtrl.authConfigList,
'user/auth/change/force/status': userAuthConfigCtrl.changeForceStatus,
'user/auth/change/locked/status': userAuthConfigCtrl.changeLockedStatus,
'user/auth/reset/totp': userAuthConfigCtrl.resetTotp,
//热门交易对搜索
'hot/pair/config/list': hotPairConfigCtrl.list,
'hot/pair/config/add': hotPairConfigCtrl.add,
'hot/pair/config/update': hotPairConfigCtrl.update,
'hot/pair/config/del': hotPairConfigCtrl.del,
//消息通知
'notice/list': noticeCtrl.list,
'notice/add': noticeCtrl.add,
'notice/update': noticeCtrl.update,
//日志和审计
'mUser/opt/log/list':mUserOptLogCtrl.list,//Madex 用户操作日志列表
//Madex 用户管理
'mUser/manage/userList': mUserManageCtrl.userList,//Madex 用户管理 ->用户列表
'mUser/manage/oneUserDetail': mUserManageCtrl.oneUserDetail,//Madex 用户管理 ->单个用户详情
'mUser/manage/updateUserEmail': mUserManageCtrl.updateUserEmail,//Madex 用户管理 ->修改用户邮箱
'mUser/manage/lockAccount': mUserManageCtrl.lockAccount,//Madex 用户管理 ->锁定账户
'mUser/manage/unlockAccount': mUserManageCtrl.unlockAccount,//Madex 用户管理 ->解锁账户
'mUser/manage/clearLoginLimit': mUserManageCtrl.clearLoginLimit,//Madex 用户管理 ->清除登陆限制
'mUser/manage/clear24WithdrawLimit': mUserManageCtrl.clear24WithdrawLimit,//Madex 用户管理 ->清除24小时提现限制
'mUser/manage/kyc/list': mUserRealNameCtrl.kycList,//Madex 用户管理 ->实名认证列表
'mUser/manage/kyc/oneDetail': mUserRealNameCtrl.oneDetail,//Madex 用户管理 ->kyc详情
'mUser/manage/kyc/audit': mUserRealNameCtrl.audit,//Madex 用户管理 ->kyc审核
};
......
......@@ -7,8 +7,8 @@ const {
} = require("@madex/ex-js-public");
let cmdWhiteList = {'i18n/info/list': 1,
let cmdWhiteList = {
'i18n/info/list': 1,
'i18n/info/add': 1,
'i18n/info/update': 1,
'i18n/info/del': 1,
......@@ -54,6 +54,17 @@ let cmdWhiteList = {'i18n/info/list': 1,
'notice/list': 1,
'notice/add': 1,
'notice/update': 1,
'mUser/opt/log/list': 1,
'mUser/manage/userList': 1,
'mUser/manage/oneUserDetail': 1,
'mUser/manage/updateUserEmail': 1,
'mUser/manage/lockAccount': 1,
'mUser/manage/unlockAccount': 1,
'mUser/manage/clearLoginLimit': 1,
'mUser/manage/clear24WithdrawLimit': 1,
'mUser/manage/kyc/list': 1,
'mUser/manage/kyc/oneDetail': 1,
'mUser/manage/kyc/audit': 1,
};
......
let { ossUtils } = require('@madex/ex-js-common');
let { logger } = require('@madex/ex-js-public');
const sizeOf = require('image-size');
const axios = require("axios");
/**
* 获取访问链接
* @param url
*/
export const getKycImageUrl = async function (url: string) {
return await getSignatureUrl(url)
}
/**
* 获取签名后的图片链接
* @param url
* @param style
*/
async function getSignatureUrl(url: string, style?: string | any) {
let res: string | any;
let newUrl = url.replace(/^\/+/, '');
if (style) {
res = await ossUtils.getUrlResize(newUrl, style);
}
else {
res = await ossUtils.getUrl(newUrl);
}
return res;
}
export const resizeWithWaterMark = async function (url: string, text: string, font_size?: number) {
let style = await watermarkStyle(text, font_size ? font_size : 60)
return await getSignatureUrl(url, style);
}
export const getImageWidth = async function (urlStr: string) {
try {
let response = await axios({
url: urlStr,
method: 'GET',
responseType: 'arraybuffer'
});
let dimensions = sizeOf(response.data);
let width = dimensions ? dimensions.width : 0;
return width;
}
catch (e) {
logger.error("OSSUtils.getImageWidth.error:" + e);
return 0;
}
}
export const withWaterMark = async function (url: string, text: string) {
let imgUrl = await getKycImageUrl(url);
let imageWidth = await getImageWidth(imgUrl);
if (imageWidth <= 0) {
imageWidth = 1000;
}
let fontSize = (imageWidth / 5);
if (fontSize > 999) {
fontSize = 999;
}
let style = await watermarkStyle(text, fontSize);
return await getSignatureUrl(url, style);
}
export const watermarkStyle = async function (text: string, font_size?: number) {
let base64 = Buffer.from(text).toString('base64');
let textWatermark = base64.replace("+", "-").replace('/', '_').replace("=", "");
return "/watermark,text_" + textWatermark + ",g_center,x_10,y_10,t_10,fill_1,color_FFFFFF,size_" + font_size ? font_size : "";
}
import * as ReqUtils from "./req-utils";
import { ErrorCode } from "../constant/errorCode";
import { aclUserInfo } from "@madex/ex-ts-dao";
let { logger } = require("@madex/ex-js-public");
import { AclUserInfoConst } from "../constant/aclUserConstant";
import * as userAuthConfigService from "../../src/functional/mvc/service/userAuthConfig.service";
let { apiAssertUtils: ApiAssert, BigNumberUtils } = require('@madex/ex-js-public');
let { authCommon: AuthCommon, redisUtilsCommon: RedisClient, } = require('@madex/ex-js-common');
/**
* 获取当前登陆用户信息
* @param sessionId
......@@ -84,4 +88,17 @@ export const getOneAclUserByAccount = async function (account: string) {
throw ErrorCode.USER_NOT_EXIST
}
return dbInfo;
}
export const checkTotp = async function (user_id: number, totp_code: string) {
//获取谷歌密钥并验证
let authInfo = await userAuthConfigService.findByUserId(user_id)
ApiAssert.isTrue(ErrorCode.UNBOUND_TOTP, authInfo && authInfo.totp_encrypt !== '');
await AuthCommon.totpCheckSync(totp_code, authInfo.totp_encrypt)
//判断是否已经使用过
let latestVerifiedKey = "bastard.totp.used.user." + user_id
let latestUsed = RedisClient.getSync(latestVerifiedKey)
ApiAssert.isFalse(ErrorCode.TOTP_CODE_USED, totp_code === latestUsed)
await RedisClient.writeSync(latestVerifiedKey, totp_code, 60 * 60)
}
\ No newline at end of file
/**
* 可操作用户最小UID
*/
export let UID_MIN = 1000;
/**
* 受限用户
*/
export let UID_LIMIT: number[] = []
/**
* uid 是否受到限制
* @param user_id
*/
export const isLimitUserId = function (user_id: number) {
return user_id <= UID_MIN || UID_LIMIT.includes(user_id);
}
\ No newline at end of file
import { userInfo } from "@madex/ex-ts-dao";
import { requestUtils, logger } from "@madex/ex-js-public";
import { config } from "@madex/ex-js-common";
import { ErrorCode } from "../constant/errorCode";
let emailServiceUrl = config.email_service_url;
export const getMUserInfoByUid = async function (m_user_id: number) {
let dbInfo = await userInfo.prototype.findOne({
where: {
user_id: m_user_id
},
raw: true
});
return dbInfo ? dbInfo : null
}
export const getMUserInfoByEmail = async function (email: string) {
let dbInfo = await userInfo.prototype.findOne({
where: {
email: email
},
raw: true
});
return dbInfo ? dbInfo : null
}
export const sendEmail = async function (email: string, m_user_id: number, template: string, params?: any, lang?: string) {
try {
let form = {
to: email,
user_id: m_user_id,
templateType: template,
params: params ? params : "{}"
};
if (lang) {
form["lang"] = lang;
}
requestUtils.doRequest(emailServiceUrl, form, () => {
});
}
catch (e) {
logger.error("mUserUtils.sendEmail.error:" + e);
}
}
export const updateMUserInfo = async function (user_id: number, updateInfo: any) {
if (!user_id || !updateInfo) {
throw ErrorCode.PARAM_MISS;
}
updateInfo.updatedAt = new Date();
await userInfo.prototype.update(updateInfo, {
where: {
user_id: user_id
}
});
}
\ No newline at end of file
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