Browse Source

app巡检接口

release_0.0.1
巴林闲侠 2 years ago
parent
commit
7f8a7f83ff
  1. 7
      api/.vscode/launch.json
  2. 59
      api/app/lib/controllers/alarm/app.js
  3. 38
      api/app/lib/controllers/auth/index.js
  4. 157
      api/app/lib/controllers/organization/index.js
  5. 25
      api/app/lib/controllers/project/index.js
  6. 6
      api/app/lib/middlewares/authenticator.js
  7. 28
      api/app/lib/models/app_inspection.js
  8. 29
      api/app/lib/models/user.js
  9. 13
      api/app/lib/routes/alarm/index.js
  10. 6
      api/app/lib/routes/auth/index.js
  11. 17
      api/app/lib/routes/organization/index.js
  12. 8
      api/app/lib/routes/project/index.js
  13. 30
      api/config.js
  14. 2
      api/sequelize-automate.config.js

7
api/.vscode/launch.json

@ -22,7 +22,12 @@
"--apiEmisUrl http://10.8.30.112:14000", "--apiEmisUrl http://10.8.30.112:14000",
"--godUrl https://restapi.amap.com/v3", "--godUrl https://restapi.amap.com/v3",
"--godKey 21c2d970e1646bb9a795900dd00093ce", "--godKey 21c2d970e1646bb9a795900dd00093ce",
"--mqttVideoServer mqtt://10.8.30.71:30883" "--mqttVideoServer mqtt://10.8.30.71:30883",
"--qnak XuDgkao6cL0HidoMAPnA5OB10Mc_Ew08mpIfRJK5",
"--qnsk yewcieZLzKZuDfig0wLZ9if9jKp2P_1jd3CMJPSa",
"--qnbkt dev-operational-service",
// "--qndmn http://resources.anxinyun.cn",
"--qndmn http://rhvqdivo5.hn-bkt.clouddn.com",
] ]
}, },
{ {

59
api/app/lib/controllers/alarm/app.js

@ -0,0 +1,59 @@
'use strict';
const moment = require('moment')
async function inspection (ctx) {
try {
const models = ctx.fs.dc.models;
const { projectAppId, screenshot = [] } = ctx.request.body
const now = moment().format()
const storageData = screenshot.map(s => {
return {
projectAppId,
screenshot: [s],
createTime: now,
}
})
await models.AppInspection.bulkCreate(storageData)
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function noted (ctx) {
try {
const models = ctx.fs.dc.models;
const { inspectionId } = ctx.request.body
const { userId } = ctx.fs.api
await models.AppInspection.update({
notedPepUserId: userId,
notedTime: moment().format()
}, {
where: {
id: inspectionId
}
})
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
inspection,
noted,
};

38
api/app/lib/controllers/auth/index.js

@ -19,18 +19,48 @@ async function login (ctx, next) {
} else { } else {
const pomsRegisterRes = await models.User.findOne({ const pomsRegisterRes = await models.User.findOne({
where: { where: {
pepUserId: emisLoginRes.id pepUserId: emisLoginRes.id,
$or: {
deleted: false,
role: { $contains: ['admin'] }
}
} }
}) })
if (!pomsRegisterRes) { if (!pomsRegisterRes) {
throw '当前账号尚未在此系统启用' throw '当前账号尚未在此系统启用'
} else if (
pomsRegisterRes.disable && (!pomsRegisterRes.role || !pomsRegisterRes.role.includes('admin'))
) {
throw '当前账号已禁用'
} }
emisLoginRes.pomsUserInfo = pomsRegisterRes.dataValues emisLoginRes.pomsUserInfo = pomsRegisterRes.dataValues
await models.User.update({ let userUpdateData = {
lastInTime: moment().format(), lastInTime: moment().format(),
inTimes: pomsRegisterRes.inTimes + 1 inTimes: pomsRegisterRes.inTimes + 1,
}, { lastInAddress: ''
}
try {
// 获取ip转为地点并记录
let ip =
// '117.90.39.49' ||
ctx.ip
if (ip && /^(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)$/.test(ip)) {
const ipLocationRes = await ctx.app.fs.godRequest.post('ip', {
query: {
ip,
}
})
if (ipLocationRes) {
userUpdateData.lastInAddress = ipLocationRes.province + ipLocationRes.city
}
}
} catch (error) {
ctx.fs.logger.error(`IP GET, error: ${error}`);
}
await models.User.update(userUpdateData, {
where: { where: {
id: emisLoginRes.id id: emisLoginRes.id
} }

157
api/app/lib/controllers/organization/index.js

@ -0,0 +1,157 @@
'use strict';
async function allDeps (ctx) {
try {
const models = ctx.fs.dc.models;
const { redis } = ctx.app
let depRes = await redis.get('allDepartments')
if (depRes) {
depRes = JSON.parse(depRes)
depRes = depRes.departments
}
ctx.status = 200;
ctx.body = depRes || []
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
}
}
}
async function editUser (ctx) {
try {
const models = ctx.fs.dc.models;
const { pepUserId, role = [], correlationProject = [] } = ctx.request.body
const existUserRes = await models.User.findOne({
where: {
pepUserId
}
})
let storageData = {
pepUserId,
role,
correlationProject,
updateTime: moment().format()
}
if (existUserRes) {
// 存在且传递id 或者 不传id也存在
// 修改 update
if (
role.includes('admin')
) {
storageData.role = [...new Set([...existUserRes.role, ...role])]
storageData.disabled = false
}
await models.User.update(storageData, {
where: {
pepUserId
}
})
} else {
// 新增
await models.User.create(storageData)
}
ctx.status = 200
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
}
}
}
async function putUser (ctx) {
try {
const models = ctx.fs.dc.models;
const { pomsUserId } = ctx.params
const { disabled = undefined, deleted = undefined } = ctx.request.body
const updateData = {
disabled,
deleted,
}
for (let k in updateData) {
if (updateData[k] == undefined) {
delete updateData[k]
}
}
await models.User.update(updateData, {
where: {
id: pomsUserId
}
})
ctx.status = 204
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
}
}
}
async function user (ctx) {
try {
const models = ctx.fs.dc.models;
const { role, limit, page, } = ctx.query
const excludeField = ['lastInTime', 'inTimes', 'onlineDuration', 'lastInAddress', 'deleted', 'updateTime']
let findOption = {
attributes: {
exclude: excludeField,
},
where: {
deleted: false,
},
order: [['updateTime', 'DESC']]
}
if (role) {
findOption.where.role = { $contains: [role] }
}
if (limit) {
findOption.limit = limit
}
if (page && limit) {
findOption.offset = page * limit
}
const userRes = await models.User.findAndCountAll(findOption)
const adminRes = await models.User.findAll({
where: {
role: { $contains: ['admin'] }
},
attributes: {
exclude: excludeField,
},
order: [['updateTime', 'DESC']]
})
ctx.status = 200
ctx.body = {
admin: adminRes,
users: userRes
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
}
}
}
module.exports = {
allDeps,
editUser,
putUser,
user,
};

25
api/app/lib/controllers/project/index.js

@ -0,0 +1,25 @@
'use strict';
async function appList (ctx) {
try {
const models = ctx.fs.dc.models;
const appRes = await models.ProjectApp.findAll({
attributes: {
exclude: ['projectId']
}
})
ctx.status = 200;
ctx.body = appRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
appList
};

6
api/app/lib/middlewares/authenticator.js

@ -70,10 +70,12 @@ let authorizeToken = async function (ctx, token) {
const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g; const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g;
if (token && tokenFormatRegexp.test(token)) { if (token && tokenFormatRegexp.test(token)) {
try { try {
const expired = await ctx.redis.hget(token, 'expired');
const authorizeRes = await ctx.app.fs.emisRequest.get('authorize', {
query: { token }
})
const { userInfo, expired } = authorizeRes;
if (expired && moment().valueOf() <= moment(expired).valueOf()) { if (expired && moment().valueOf() <= moment(expired).valueOf()) {
const userInfo = JSON.parse(await ctx.redis.hget(token, 'userInfo'));
rslt = { rslt = {
'authorized': userInfo.authorized, 'authorized': userInfo.authorized,
'resources': (userInfo || {}).resources || [], 'resources': (userInfo || {}).resources || [],

28
api/app/lib/models/app_inspection.js

@ -15,14 +15,18 @@ module.exports = dc => {
autoIncrement: true, autoIncrement: true,
unique: "app_inspection_id_uindex" unique: "app_inspection_id_uindex"
}, },
pepProjectId: { projectAppId: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
allowNull: true, allowNull: true,
defaultValue: null, defaultValue: null,
comment: null, comment: null,
primaryKey: false, primaryKey: false,
field: "pep_project_id", field: "project_app_id",
autoIncrement: false autoIncrement: false,
references: {
key: "id",
model: "projectApp"
}
}, },
createTime: { createTime: {
type: DataTypes.DATE, type: DataTypes.DATE,
@ -41,6 +45,24 @@ module.exports = dc => {
primaryKey: false, primaryKey: false,
field: "screenshot", field: "screenshot",
autoIncrement: false autoIncrement: false
},
notedPepUserId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: "核验人员",
primaryKey: false,
field: "noted_pep_user_id",
autoIncrement: false
},
notedTime: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "noted_time",
autoIncrement: false
} }
}, { }, {
tableName: "app_inspection", tableName: "app_inspection",

29
api/app/lib/models/user.js

@ -63,7 +63,7 @@ module.exports = dc => {
onlineDuration: { onlineDuration: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
allowNull: true, allowNull: true,
defaultValue: null, defaultValue: "0",
comment: "在线时长 单位 s", comment: "在线时长 单位 s",
primaryKey: false, primaryKey: false,
field: "online_duration", field: "online_duration",
@ -77,6 +77,33 @@ module.exports = dc => {
primaryKey: false, primaryKey: false,
field: "last_in_address", field: "last_in_address",
autoIncrement: false autoIncrement: false
},
disabled: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "disabled",
autoIncrement: false
},
deleted: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "deleted",
autoIncrement: false
},
updateTime: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: sequelize.fn('now'),
comment: null,
primaryKey: false,
field: "update_time",
autoIncrement: false
} }
}, { }, {
tableName: "user", tableName: "user",

13
api/app/lib/routes/alarm/index.js

@ -0,0 +1,13 @@
'use strict';
const application = require('../../controllers/alarm/app');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['POST/alarm/application/inspection'] = { content: '保存应用巡检信息', visible: true };
router.post('/alarm/application/inspection', application.inspection);
app.fs.api.logAttr['PUT/alarm/application/noted'] = { content: '保存检验状态', visible: true };
router.put('/alarm/application/noted', application.noted);
};

6
api/app/lib/routes/auth/index.js

@ -3,15 +3,9 @@
const auth = require('../../controllers/auth'); const auth = require('../../controllers/auth');
module.exports = function (app, router, opts) { module.exports = function (app, router, opts) {
/**
* @api {Post} login 登录.
* @apiVersion 1.0.0
* @apiGroup Auth
*/
app.fs.api.logAttr['POST/login'] = { content: '登录', visible: true }; app.fs.api.logAttr['POST/login'] = { content: '登录', visible: true };
router.post('/login', auth.login); router.post('/login', auth.login);
app.fs.api.logAttr['PUT/logout'] = { content: '登出', visible: false }; app.fs.api.logAttr['PUT/logout'] = { content: '登出', visible: false };
router.put('/logout', auth.logout); router.put('/logout', auth.logout);
}; };

17
api/app/lib/routes/organization/index.js

@ -0,0 +1,17 @@
'use strict';
const organization = require('../../controllers/organization');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/organization/deps'] = { content: '获取全部部门及其下用户', visible: true };
router.get('/organization/deps', organization.allDeps);
app.fs.api.logAttr['POST/organization/user'] = { content: '编辑成员', visible: true };
router.post('/organization/user', organization.editUser);
app.fs.api.logAttr['PUT/organization/user/:pomsUserId'] = { content: '修改成员状态', visible: true };
router.put('/organization/user/:pomsUserId', organization.putUser);
app.fs.api.logAttr['GET/organization/user'] = { content: '获取成员列表', visible: true };
router.get('/organization/user', organization.user);
};

8
api/app/lib/routes/project/index.js

@ -0,0 +1,8 @@
'use strict';
const project = require('../../controllers/project');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/project/app_list'] = { content: '获取应用列表', visible: true };
router.get('/project/app_list', project.appList);
};

30
api/config.js

@ -24,6 +24,12 @@ args.option('godKey', '高德地图API key');
args.option('mqttVideoServer', '视频后台 mqtt 服务 URL'); args.option('mqttVideoServer', '视频后台 mqtt 服务 URL');
// 七牛云存储参数
args.option('qnak', 'qiniuAccessKey');
args.option('qnsk', 'qiniuSecretKey');
args.option('qnbkt', 'qiniuBucket');
args.option('qndmn', 'qiniuDomain');
const flags = args.parse(process.argv); const flags = args.parse(process.argv);
const POMS_DB = process.env.POMS_DB || flags.pg; const POMS_DB = process.env.POMS_DB || flags.pg;
@ -46,11 +52,19 @@ const GOD_KEY = process.env.GOD_KEY || flags.godKey;
// 视频后台 mqtt 信息推送地址 // 视频后台 mqtt 信息推送地址
const MQTT_VIDEO_SERVER = process.env.MQTT_VIDEO_SERVER || flags.mqttVideoServer; const MQTT_VIDEO_SERVER = process.env.MQTT_VIDEO_SERVER || flags.mqttVideoServer;
// 七牛云存储参数
const QINIU_DOMAIN_QNDMN_RESOURCE = process.env.ANXINCLOUD_QINIU_DOMAIN_QNDMN_RESOURCE || flags.qndmn;
const QINIU_BUCKET_RESOURCE = process.env.ANXINCLOUD_QINIU_BUCKET_RESOURCE || flags.qnbkt;
const QINIU_AK = process.env.ANXINCLOUD_QINIU_ACCESSKEY || flags.qnak;
const QINIU_SK = process.env.ANXINCLOUD_QINIU_SECRETKEY || flags.qnsk;
if ( if (
!POMS_DB || !POMS_DB ||
!IOTA_REDIS_SERVER_HOST || !IOTA_REDIS_SERVER_PORT || !GOD_KEY || !MQTT_VIDEO_SERVER || !IOTA_REDIS_SERVER_HOST || !IOTA_REDIS_SERVER_PORT || !GOD_KEY || !MQTT_VIDEO_SERVER ||
!AXY_API_URL || !AXY_API_URL ||
!API_EMIS_URL !API_EMIS_URL ||
!QINIU_DOMAIN_QNDMN_RESOURCE || !QINIU_BUCKET_RESOURCE || !QINIU_AK || !QINIU_SK
) { ) {
console.log('缺少启动参数,异常退出'); console.log('缺少启动参数,异常退出');
args.showHelp(); args.showHelp();
@ -64,10 +78,11 @@ const product = {
{ {
entry: require('@fs/attachment').entry, entry: require('@fs/attachment').entry,
opts: { opts: {
local: { qiniu: {
origin: IOT_VIDEO_ACCESS_LOCAL_SVR_ORIGIN || `http://localhost:${flags.port || 8080}`, domain: QINIU_DOMAIN_QNDMN_RESOURCE,
rootPath: 'static', bucket: QINIU_BUCKET_RESOURCE,
childPath: 'upload', accessKey: QINIU_AK,
secretKey: QINIU_SK
}, },
maxSize: 104857600, // 100M maxSize: 104857600, // 100M
} }
@ -76,8 +91,9 @@ const product = {
opts: { opts: {
dev, dev,
exclude: [ exclude: [
{ p: '/camera', o: 'GET' }, // 暂时滴 { p: '/attachments/:p', o: 'POST' },
{ p: '/application/check', o: 'GET' }, // 暂时滴 { p: '/alarm/application/inspection', o: 'POST' },
{ p: '/project/app_list', o: 'GET' }
], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由 ], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由
redis: { redis: {
host: IOTA_REDIS_SERVER_HOST, host: IOTA_REDIS_SERVER_HOST,

2
api/sequelize-automate.config.js

@ -26,7 +26,7 @@ module.exports = {
dir: './app/lib/models', // 指定输出 models 文件的目录 dir: './app/lib/models', // 指定输出 models 文件的目录
typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义 typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义
emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir` emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir`
tables: null, // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性 tables: ['app_inspection'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性 skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性
tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中 tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中
ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面 ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面

Loading…
Cancel
Save