diff --git a/api/app/lib/controllers/auth/index.js b/api/app/lib/controllers/auth/index.js
index 4ddaa8a..705cafe 100644
--- a/api/app/lib/controllers/auth/index.js
+++ b/api/app/lib/controllers/auth/index.js
@@ -5,7 +5,7 @@ const MD5 = require('crypto-js/md5');
const moment = require('moment');
const uuid = require('uuid');
-async function login (ctx, next) {
+async function login(ctx, next) {
try {
// const transaction = await ctx.fs.dc.orm.transaction();
@@ -16,10 +16,13 @@ async function login (ctx, next) {
where: {
username: params.username,
password: password,
- }
+ },
+ include: [{
+ attributes: ["resourceCode"],
+ model: models.UserResource
+ }]
});
-
if (userRes) {
const token = uuid.v4();
const userInfo = {
@@ -35,6 +38,15 @@ async function login (ctx, next) {
userInfo: userInfo,
expired: expired
});
+
+ await models.OperationLog.create({
+ time: new Date().getTime(),
+ clientType: ctx.header['user-agent'],
+ content: '登录',
+ parameter: null,
+ userId: userInfo.id,
+ })
+
ctx.status = 200;
ctx.body = userInfo
} else {
@@ -54,7 +66,7 @@ async function login (ctx, next) {
}
}
-async function varfiyCode (ctx) {
+async function varfiyCode(ctx) {
try {
const { models } = ctx.fs.dc;
const { pushBySms, pushByEmail } = ctx.app.fs.utils
@@ -104,17 +116,32 @@ async function varfiyCode (ctx) {
}
}
-async function logout (ctx) {
+async function logout(ctx) {
try {
const models = ctx.fs.dc.models;
const params = ctx.request.body;
+ const userInfo = await models.UserToken.findOne({
+ where: {
+ token: params.token,
+ },
+ attributes: ["userInfo"],
+ raw: true,
+ });
await models.UserToken.destroy({
where: {
token: params.token,
}
});
+ await models.OperationLog.create({
+ time: new Date().getTime(),
+ clientType: ctx.header['user-agent'],
+ content: '登出',
+ parameter: null,
+ userId: userInfo.userInfo.id,
+ })
+
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
diff --git a/api/app/lib/controllers/bigScreen/index .js b/api/app/lib/controllers/bigScreen/index .js
index 0553f5b..dae060a 100644
--- a/api/app/lib/controllers/bigScreen/index .js
+++ b/api/app/lib/controllers/bigScreen/index .js
@@ -34,7 +34,7 @@ const getAnxinyunToken = async function (ctx) {
ctx.fs.logger.error(`sechedule: laborAttendance, error: ${error}`);
}
}
-async function axyData (ctx, next) {
+async function axyData(ctx, next) {
try {
let { type, url, params = {} } = ctx.request.body;
@@ -116,7 +116,7 @@ const getVideoUrl = async function (ctx) {
}
-async function getDevices (ctx, next) {
+async function getDevices(ctx, next) {
try {
let { thingId } = ctx.query;
@@ -133,7 +133,7 @@ async function getDevices (ctx, next) {
}
-async function getInstances (ctx, next) {
+async function getInstances(ctx, next) {
try {
let { thingId } = ctx.query;
@@ -150,13 +150,23 @@ async function getInstances (ctx, next) {
}
-async function getCapabilitiesInvoke (ctx, next) {
+async function getCapabilitiesInvoke(ctx, next) {
try {
+ const models = ctx.fs.dc.models;
let data = ctx.query;
const res = await ctx.app.iota.request.post(`/capabilities/invoke`, data) || {}
+ const userId = ctx.fs.api.userId;
+ await models.OperationLog.create({
+ time: new Date().getTime(),
+ clientType: ctx.header['user-agent'],
+ content: `下发泵站控制指令`,
+ parameter: null,
+ userId,
+ })
+
ctx.status = 200;
ctx.body = res.body;
} catch (err) {
diff --git a/api/app/lib/controllers/operationLogs/index.js b/api/app/lib/controllers/operationLogs/index.js
new file mode 100644
index 0000000..0beaebe
--- /dev/null
+++ b/api/app/lib/controllers/operationLogs/index.js
@@ -0,0 +1,49 @@
+'use strict';
+
+async function getLog(ctx, next) {
+ try {
+ const models = ctx.fs.dc.models;
+ const { limit, page, startTime, endTime, keyword } = ctx.query
+
+ let findOption = {
+ where: {},
+ order: [['time', 'DESC']],
+ include: [{
+ model: models.User,
+ attributes: ["name", "username"],
+ }],
+ distinct: true
+ }
+ if (limit) {
+ findOption.limit = Number(limit)
+ }
+ if (page && limit) {
+ findOption.offset = page * limit
+ }
+ if (startTime && endTime) {
+ findOption.where.time = { $between: [startTime, endTime] };
+ }
+ if (keyword) {
+ findOption.where['$or'] = {
+ clientType: { $like: `%${keyword}%` },
+ content: { $like: `%${keyword}%` },
+ parameter: { $like: `%${keyword}%` },
+ }
+ }
+
+ const res = await models.OperationLog.findAndCountAll(findOption)
+
+ ctx.status = 200;
+ ctx.body = res
+ } catch (error) {
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = {
+ "message": "获取操作日志失败"
+ }
+ }
+}
+
+module.exports = {
+ getLog,
+}
\ No newline at end of file
diff --git a/api/app/lib/controllers/organization/authority.js b/api/app/lib/controllers/organization/authority.js
new file mode 100644
index 0000000..6960c1e
--- /dev/null
+++ b/api/app/lib/controllers/organization/authority.js
@@ -0,0 +1,102 @@
+async function getResource(ctx, next) {
+ try {
+ const models = ctx.fs.dc.models;
+
+ const res = await models.Resource.findAll({
+ where: { parentCode: null },
+ include: [{
+ model: models.Resource,
+ }]
+ })
+
+ ctx.body = res;
+ ctx.status = 200;
+
+ } catch (error) {
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = {
+ "message": "查询所有权限数据失败"
+ }
+ }
+}
+async function getUserResource(ctx, next) {
+ try {
+ const models = ctx.fs.dc.models;
+ const { userId } = ctx.query;
+
+ const res = await models.UserResource.findAll({
+ where: { userId: userId },
+ include: [{
+ model: models.Resource,
+ }]
+ })
+
+ ctx.body = res;
+ ctx.status = 200;
+
+ } catch (error) {
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = {
+ "message": "查询用户权限数据失败"
+ }
+ }
+}
+
+async function updateUserRes(ctx, next) {
+ const transaction = await ctx.fs.dc.orm.transaction();
+ try {
+ const models = ctx.fs.dc.models;
+ const { userId, resCode } = ctx.request.body;
+
+ const res = await models.UserResource.findAll({
+ attributes: ["resourceCode"],
+ raw: true,
+ where: { userId: userId }
+ })
+
+ const addRes = resCode.filter(r => !res.some(rr => rr.resourceCode == r)).map(r => { return { userId: userId, resourceCode: r } });
+ const delRes = res.filter(r => !resCode.includes(r.resourceCode)).map(r => r.resourceCode);
+ addRes.length && await models.UserResource.bulkCreate(addRes, { transaction: transaction });
+ delRes.length && await models.UserResource.destroy({
+ where: {
+ resourceCode: { $in: delRes },
+ userId: userId
+ },
+ transaction: transaction
+ })
+
+ const operationUserId = ctx.fs.api.userId;
+ const user = await models.User.findOne({
+ attributes: ["name"],
+ where: { id: userId },
+ raw: true,
+ transaction: transaction,
+ })
+ await models.OperationLog.create({
+ time: new Date().getTime(),
+ clientType: ctx.header['user-agent'],
+ content: `修改 (${user.name}) 用户权限`,
+ parameter: null,
+ userId: operationUserId,
+ }, { transaction })
+
+ ctx.status = 204;
+ await transaction.commit();
+
+ } catch (error) {
+ await transaction.rollback();
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = {
+ "message": "更新用户权限数据失败"
+ }
+ }
+}
+
+module.exports = {
+ getResource,
+ getUserResource,
+ updateUserRes
+};
\ No newline at end of file
diff --git a/api/app/lib/controllers/organization/user.js b/api/app/lib/controllers/organization/user.js
new file mode 100644
index 0000000..e5e469a
--- /dev/null
+++ b/api/app/lib/controllers/organization/user.js
@@ -0,0 +1,204 @@
+'use strict';
+const Hex = require('crypto-js/enc-hex');
+const MD5 = require('crypto-js/md5');
+
+async function getUser(ctx, next) {
+ try {
+ const models = ctx.fs.dc.models;
+ const userRes = await models.User.findAll({
+ where: {
+ delete: false
+ },
+ attributes: { exclude: ['password'] },
+ order: [['id', 'asc']],
+ })
+
+ ctx.status = 200;
+ ctx.body = userRes
+ } catch (error) {
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = {
+ "message": "获取用户信息失败"
+ }
+ }
+}
+
+async function creatUser(ctx, next) {
+ let errMsg = "新建用户失败"
+ try {
+ const models = ctx.fs.dc.models;
+ const data = ctx.request.body;
+
+ let repeatUserNameCount = await models.User.count({
+ where: {
+ username: data.username,
+ delete: false
+ }
+ })
+
+ if (repeatUserNameCount) {
+ errMsg = '已有当前用户名'
+ throw errMsg
+ }
+
+ await models.User.create({
+ name: data.name,
+ username: data.username,
+ password: Hex.stringify(MD5(data.password)),
+ delete: false,
+ })
+ const userId = ctx.fs.api.userId;
+ await models.OperationLog.create({
+ time: new Date().getTime(),
+ clientType: ctx.header['user-agent'],
+ content: `新建用户:${data.name}`,
+ parameter: null,
+ userId,
+ })
+
+ ctx.status = 204;
+ } catch (error) {
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = {
+ "message": errMsg
+ }
+ }
+}
+
+
+async function updateUser(ctx, next) {
+ let errMsg = "修改用户失败"
+ try {
+ const models = ctx.fs.dc.models;
+ const data = ctx.request.body;
+ const { id } = ctx.params;
+
+ let repeatUserNameCount = await models.User.findOne({
+ where: {
+ username: data.username,
+ delete: false
+ },
+ raw: true,
+ })
+
+ if (repeatUserNameCount && repeatUserNameCount.id != id) {
+ errMsg = '已有当前用户名'
+ throw errMsg
+ }
+
+ await models.User.update({
+ name: data.name,
+ username: data.username,
+ delete: false,
+ }, {
+ where: { id }
+ });
+
+ const userId = ctx.fs.api.userId;
+ await models.OperationLog.create({
+ time: new Date().getTime(),
+ clientType: ctx.header['user-agent'],
+ content: `修改 (${data.name}) 用户信息`,
+ parameter: null,
+ userId,
+ })
+
+ ctx.status = 204;
+ } catch (error) {
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = {
+ "message": errMsg
+ }
+ }
+}
+
+async function deleteUser(ctx, next) {
+ try {
+ const models = ctx.fs.dc.models;
+ const { ids } = ctx.params;
+ const userIds = ids.split(',');
+ const delUser = await models.User.update({
+ delete: true,
+ }, {
+ where: {
+ id: { $in: userIds },
+ },
+ returning: true,
+ });
+
+ const userId = ctx.fs.api.userId;
+ const userName = delUser[1].map(item => item.name).join()
+ await models.OperationLog.create({
+ time: new Date().getTime(),
+ clientType: ctx.header['user-agent'],
+ content: `删除用户:${userName}`,
+ parameter: null,
+ userId,
+ })
+
+ ctx.status = 204;
+ } catch (error) {
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = {
+ "message": "删除用户失败"
+ }
+ }
+}
+
+async function resetPwd(ctx, next) {
+ try {
+ const models = ctx.fs.dc.models;
+ const { id } = ctx.params;
+ const { password } = ctx.request.body;
+ if (!password) {
+ ctx.status = 400;
+ ctx.body = { "message": "请输入修改密码" };
+ return;
+ }
+ const userRes = await models.User.findOne({
+ where: { id },
+ attributes: ['id']
+ });
+ if (userRes) {
+ const updateUser = await models.User.update(
+ { password: Hex.stringify(MD5(password)) },
+ {
+ where: { id },
+ returning: true,
+ },
+ );
+ const userId = ctx.fs.api.userId;
+ await models.OperationLog.create({
+ time: new Date().getTime(),
+ clientType: ctx.header['user-agent'],
+ content: `修改 (${updateUser[1][0].name}) 用户密码`,
+ parameter: null,
+ userId,
+ })
+ ctx.status = 204;
+ } else {
+ ctx.status = 400;
+ ctx.body = {
+ "message": "用户不存在"
+ }
+ }
+ } catch (error) {
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = {
+ "message": "修改用户密码失败"
+ }
+ }
+}
+
+module.exports = {
+ getUser,
+ creatUser,
+ updateUser,
+ deleteUser,
+ resetPwd,
+}
\ No newline at end of file
diff --git a/api/app/lib/index.js b/api/app/lib/index.js
index 7684a5e..82597d7 100644
--- a/api/app/lib/index.js
+++ b/api/app/lib/index.js
@@ -11,7 +11,7 @@ const authenticator = require('./middlewares/authenticator');
//const clickHouseClient = require('./service/clickHouseClient')
const schedule = require('./schedule')
// const apiLog = require('./middlewares/api-log');
-
+
module.exports.entry = function (app, router, opts) {
app.fs.logger.log('info', '[FS-AUTH]', 'Inject auth and api mv into router.');
@@ -53,25 +53,18 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq
require(`./models/${filename}`)(dc)
});
- // const { Department, User, UserResource, Resource, Project, Point, PatrolPlan
- // } = dc.models;
-
- // UserResource.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' });
- // User.hasMany(UserResource, { foreignKey: 'userId', sourceKey: 'id' });
-
- // UserResource.belongsTo(Resource, { foreignKey: 'resourceId', targetKey: 'code' });
- // Resource.hasMany(UserResource, { foreignKey: 'resourceId', sourceKey: 'code' });
- // Resource.hasMany(Resource, { foreignKey: 'parentResource', sourceKey: 'code' });
+ const { User, UserResource, Resource, OperationLog, } = dc.models;
- // User.belongsTo(Department, { foreignKey: 'departmentId', targetKey: 'id' });
- // Department.hasMany(User, { foreignKey: 'departmentId', sourceKey: 'id' });
+ User.belongsToMany(Resource, { through: UserResource, foreignKey: 'userId', otherKey: 'resourceCode' });
+ Resource.belongsToMany(User, { through: UserResource, foreignKey: 'resourceCode', otherKey: 'userId' });
- // Point.belongsTo(Project, { foreignKey: 'projectId', targetKey: 'id' });
- // Project.hasMany(Point, { foreignKey: 'projectId', sourceKey: 'id' });
+ UserResource.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' });
+ User.hasMany(UserResource, { foreignKey: 'userId', sourceKey: 'id' });
- // PatrolPlan.belongsTo(Project, { foreignKey: 'structureId', targetKey: 'id' });
- // Project.hasMany(PatrolPlan, { foreignKey: 'structureId', sourceKey: 'id' });
+ UserResource.belongsTo(Resource, { foreignKey: 'resourceCode', targetKey: 'code' });
+ Resource.hasMany(UserResource, { foreignKey: 'resourceCode', sourceKey: 'code' });
+ Resource.hasMany(Resource, { foreignKey: 'parentCode', sourceKey: 'code' });
- // PatrolPlan.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' });
- // User.hasMany(PatrolPlan, { foreignKey: 'userId', sourceKey: 'id' });
+ OperationLog.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' });
+ User.hasMany(OperationLog, { foreignKey: 'userId', sourceKey: 'id' });
};
diff --git a/api/app/lib/models/operation_log.js b/api/app/lib/models/operation_log.js
new file mode 100644
index 0000000..9c4b648
--- /dev/null
+++ b/api/app/lib/models/operation_log.js
@@ -0,0 +1,74 @@
+/* eslint-disable*/
+'use strict';
+
+module.exports = dc => {
+ const DataTypes = dc.ORM;
+ const sequelize = dc.orm;
+ const OperationLog = sequelize.define("operationLog", {
+ id: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: true,
+ field: "id",
+ autoIncrement: true,
+ },
+ time: {
+ type: DataTypes.DATE,
+ allowNull: false,
+ defaultValue: null,
+ comment: "操作时间",
+ primaryKey: false,
+ field: "time",
+ autoIncrement: false
+ },
+ clientType: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ defaultValue: null,
+ comment: "客户端类型",
+ primaryKey: false,
+ field: "client_type",
+ autoIncrement: false
+ },
+ content: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ defaultValue: null,
+ comment: "操作内容",
+ primaryKey: false,
+ field: "content",
+ autoIncrement: false
+ },
+ parameter: {
+ type: DataTypes.STRING,
+ allowNull: true,
+ defaultValue: null,
+ comment: "操作参数",
+ primaryKey: false,
+ field: "parameter",
+ autoIncrement: false
+ },
+ userId: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: "操作用户ID",
+ primaryKey: false,
+ field: "user_id",
+ autoIncrement: false,
+ references: {
+ key: "id",
+ model: "t_user"
+ }
+ },
+ }, {
+ tableName: "t_operation_log",
+ comment: "",
+ indexes: []
+ });
+
+ dc.models.OperationLog = OperationLog;
+ return OperationLog;
+};
\ No newline at end of file
diff --git a/api/app/lib/models/resource.js b/api/app/lib/models/resource.js
new file mode 100644
index 0000000..f0a4764
--- /dev/null
+++ b/api/app/lib/models/resource.js
@@ -0,0 +1,43 @@
+/* eslint-disable*/
+'use strict';
+
+module.exports = dc => {
+ const DataTypes = dc.ORM;
+ const sequelize = dc.orm;
+ const Resource = sequelize.define("resource", {
+ code: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: true,
+ field: "code",
+ autoIncrement: false,
+ },
+ name: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "name",
+ autoIncrement: false
+ },
+ parentCode: {
+ type: DataTypes.STRING,
+ allowNull: true,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "parent_code",
+ autoIncrement: false,
+ },
+ }, {
+ tableName: "t_resource",
+ comment: "",
+ indexes: []
+ });
+
+ dc.models.Resource = Resource;
+ return Resource;
+};
\ No newline at end of file
diff --git a/api/app/lib/models/user.js b/api/app/lib/models/user.js
index a3196b9..f07f715 100644
--- a/api/app/lib/models/user.js
+++ b/api/app/lib/models/user.js
@@ -42,6 +42,15 @@ module.exports = dc => {
field: "password",
autoIncrement: false
},
+ delete: {
+ type: DataTypes.BOOLEAN,
+ allowNull: false,
+ defaultValue: false,
+ comment: null,
+ primaryKey: false,
+ field: "delete",
+ autoIncrement: false
+ },
}, {
tableName: "t_user",
comment: "",
diff --git a/api/app/lib/models/user_resource.js b/api/app/lib/models/user_resource.js
new file mode 100644
index 0000000..586d234
--- /dev/null
+++ b/api/app/lib/models/user_resource.js
@@ -0,0 +1,51 @@
+/* eslint-disable*/
+'use strict';
+
+module.exports = dc => {
+ const DataTypes = dc.ORM;
+ const sequelize = dc.orm;
+ const UserResource = sequelize.define("userResource", {
+ id: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: true,
+ field: "id",
+ autoIncrement: true,
+ },
+ userId: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "user_id",
+ autoIncrement: false,
+ references: {
+ key: "id",
+ model: "t_user"
+ }
+ },
+ resourceCode: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "resource_code",
+ autoIncrement: false,
+ references: {
+ key: "code",
+ model: "t_resource"
+ }
+ }
+ }, {
+ tableName: "t_user_resource",
+ comment: "",
+ indexes: []
+ });
+
+ dc.models.UserResource = UserResource;
+ return UserResource;
+};
\ No newline at end of file
diff --git a/api/app/lib/routes/organization/index.js b/api/app/lib/routes/bigScreen/index.js
similarity index 100%
rename from api/app/lib/routes/organization/index.js
rename to api/app/lib/routes/bigScreen/index.js
diff --git a/api/app/lib/routes/operationLogs/index.js b/api/app/lib/routes/operationLogs/index.js
new file mode 100644
index 0000000..41f6c52
--- /dev/null
+++ b/api/app/lib/routes/operationLogs/index.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const operationLog = require('../../controllers/operationLogs/index');
+
+module.exports = function (app, router, opts) {
+
+ app.fs.api.logAttr['GET/operationLog'] = { content: '获取操作日志', visible: false };
+ router.get('/operationLog', operationLog.getLog);
+
+ // app.fs.api.logAttr['POST/operationLog'] = { content: '创建操作日志', visible: false };
+ // router.post('/operationLog', operationLog.creatLog);
+
+ // app.fs.api.logAttr['PUT/operationLog/:id'] = { content: '修改操作日志', visible: false };
+ // router.put('/operationLog/:id', operationLog.updateLog);
+
+ // app.fs.api.logAttr['DEL/operationLog/:ids'] = { content: '删除操作日志', visible: false };
+ // router.del('/operationLog/:ids', operationLog.deleteLog);
+
+};
\ No newline at end of file
diff --git a/api/app/lib/routes/organization/authority.js b/api/app/lib/routes/organization/authority.js
new file mode 100644
index 0000000..99de6df
--- /dev/null
+++ b/api/app/lib/routes/organization/authority.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const Authority = require('../../controllers/organization/authority');
+
+module.exports = function (app, router, opts) {
+ /**
+ * @api {GET} resource 查询所有权限码.
+ * @apiVersion 1.0.0
+ * @apiGroup Org
+ */
+ app.fs.api.logAttr['GET/resource'] = { content: '查询所有权限码', visible: true };
+ router.get('resource', Authority.getResource);
+ /**
+ * @api {GET} user/resource 查询用户权限.
+ * @apiVersion 1.0.0
+ * @apiGroup Org
+ */
+ app.fs.api.logAttr['GET/user/resource'] = { content: '查询用户权限', visible: true };
+ router.get('user/resource', Authority.getUserResource);
+
+ /**
+ * @api {POST} user/resource 更新用户权限.
+ * @apiVersion 1.0.0
+ * @apiGroup Org
+ */
+ app.fs.api.logAttr['POST/user/resource'] = { content: '更新用户权限', visible: true };
+ router.post('user/resource', Authority.updateUserRes);
+};
\ No newline at end of file
diff --git a/api/app/lib/routes/organization/user.js b/api/app/lib/routes/organization/user.js
new file mode 100644
index 0000000..e5bf4e1
--- /dev/null
+++ b/api/app/lib/routes/organization/user.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const user = require('../../controllers/organization/user');
+
+module.exports = function (app, router, opts) {
+
+ app.fs.api.logAttr['GET/organization/user'] = { content: '获取用户信息', visible: false };
+ router.get('/organization/user', user.getUser);
+
+ app.fs.api.logAttr['POST/organization/user'] = { content: '创建用户信息', visible: false };
+ router.post('/organization/user', user.creatUser);
+
+ app.fs.api.logAttr['PUT/organization/user/:id'] = { content: '修改用户信息', visible: false };
+ router.put('/organization/user/:id', user.updateUser);
+
+ app.fs.api.logAttr['DEL/organization/user/:ids'] = { content: '删除用户信息', visible: false };
+ router.del('/organization/user/:ids', user.deleteUser);
+
+ app.fs.api.logAttr['PUT/organization/user/resetPwd/:id'] = { content: '重置用户密码', visible: false };
+ router.put('/organization/user/resetPwd/:id', user.resetPwd);
+
+};
\ No newline at end of file
diff --git a/scripts/0.4/data/1.add_user.sql b/scripts/0.4/data/1.add_user.sql
new file mode 100644
index 0000000..a796963
--- /dev/null
+++ b/scripts/0.4/data/1.add_user.sql
@@ -0,0 +1,16 @@
+INSERT INTO
+ "public"."t_user" (
+ "id",
+ "name",
+ "username",
+ "password",
+ "delete"
+ )
+VALUES
+ (
+ default,
+ '超级管理员',
+ 'SuperAdmin',
+ 'e10adc3949ba59abbe56e057f20f883e',
+ 'f'
+ );
\ No newline at end of file
diff --git a/scripts/0.4/data/2.add_user_resource.sql b/scripts/0.4/data/2.add_user_resource.sql
new file mode 100644
index 0000000..0ca192f
--- /dev/null
+++ b/scripts/0.4/data/2.add_user_resource.sql
@@ -0,0 +1,47 @@
+INSERT INTO "public"."t_resource" VALUES ('ORG_MANAGE', '组织管理', NULL);
+INSERT INTO "public"."t_resource" VALUES ('ORG_MEMBER', '用户管理', 'ORG_MANAGE');
+INSERT INTO "public"."t_resource" VALUES ('ORG_AUTH', '权限配置', 'ORG_MANAGE');
+INSERT INTO "public"."t_resource" VALUES ('OPERATION_LOG', '操作日志', NULL);
+INSERT INTO "public"."t_resource" VALUES ('OPERATION_LOG_VIEW', '操作日志查看', 'OPERATION_LOG');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_CONTROL', '泵站控制', NULL);
+INSERT INTO "public"."t_resource" VALUES ('PUMP_WATER_CONTROL', '泵站水泵控制', 'PUMP_CONTROL');
+INSERT INTO "public"."t_resource" VALUES ('MONITORING_SCOPE', '泵站监测', NULL);
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3569', '八月湖二站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3590', '张坊电排站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3592', '东山电排站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3593', '利用站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3594', '杨家湾站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3595', '汇仁大道补水站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3596', '河下电排站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3597', '石岐补水站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3598', '石岐电排站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3599', '三山电排站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3600', '万寿湖电排站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3601', '河外电排站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3642', '沥山电排站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3652', '象湖泵站', 'MONITORING_SCOPE');
+INSERT INTO "public"."t_resource" VALUES ('PUMP_STATION_3653', '雄溪泵站', 'MONITORING_SCOPE');
+
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'ORG_MANAGE');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'ORG_MEMBER');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'ORG_AUTH');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'OPERATION_LOG');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'OPERATION_LOG_VIEW');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_CONTROL');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_WATER_CONTROL');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'MONITORING_SCOPE');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3569');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3590');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3592');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3593');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3594');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3595');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3596');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3597');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3598');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3599');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3600');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3601');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3642');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3652');
+INSERT INTO "public"."t_user_resource" VALUES (default, 1, 'PUMP_STATION_3653');
\ No newline at end of file
diff --git a/scripts/0.4/schema/1.create_organization_table.sql b/scripts/0.4/schema/1.create_organization_table.sql
new file mode 100644
index 0000000..a6fd2fb
--- /dev/null
+++ b/scripts/0.4/schema/1.create_organization_table.sql
@@ -0,0 +1,30 @@
+DROP TABLE IF EXISTS "public"."t_user";
+CREATE TABLE "public"."t_user" (
+ "id" serial,
+ "name" varchar(64) NOT NULL,
+ "username" varchar(64) NOT NULL,
+ "password" varchar(255) NOT NULL,
+ "delete" bool NOT NULL DEFAULT false,
+ PRIMARY KEY ("id")
+);
+COMMENT ON COLUMN "public"."t_user"."username" IS '用户名 账号';
+
+
+DROP TABLE IF EXISTS "public"."t_resource";
+CREATE TABLE "public"."t_resource" (
+ "code" varchar(128) NOT NULL,
+ "name" varchar(128) NOT NULL,
+ "parent_code" varchar(128),
+ PRIMARY KEY ("code")
+);
+
+
+DROP TABLE IF EXISTS "public"."t_user_resource";
+CREATE TABLE "public"."t_user_resource" (
+ "id" serial,
+ "user_id" int4 NOT NULL,
+ "resource_code" varchar(128) NOT NULL,
+ PRIMARY KEY ("id"),
+ CONSTRAINT "user_resource_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."t_user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "user_resource_resource_code_fk" FOREIGN KEY ("resource_code") REFERENCES "public"."t_resource" ("code") ON DELETE NO ACTION ON UPDATE NO ACTION
+);
\ No newline at end of file
diff --git a/scripts/0.4/schema/2.create_operation_log.sql b/scripts/0.4/schema/2.create_operation_log.sql
new file mode 100644
index 0000000..57d01fb
--- /dev/null
+++ b/scripts/0.4/schema/2.create_operation_log.sql
@@ -0,0 +1,22 @@
+DROP TABLE IF EXISTS "public"."t_operation_log";
+
+CREATE TABLE "public"."t_operation_log" (
+ "id" serial,
+ "time" timestamptz NOT NULL,
+ "client_type" varchar(512) NOT NULL,
+ "content" varchar(255) NOT NULL,
+ "parameter" varchar(512),
+ "user_id" int4 NOT NULL,
+ PRIMARY KEY ("id"),
+ CONSTRAINT "operation_log_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."t_user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+);
+
+COMMENT ON COLUMN "public"."t_operation_log"."time" IS '操作时间';
+
+COMMENT ON COLUMN "public"."t_operation_log"."client_type" IS '客户端类型';
+
+COMMENT ON COLUMN "public"."t_operation_log"."content" IS '操作内容';
+
+COMMENT ON COLUMN "public"."t_operation_log"."parameter" IS '操作参数';
+
+COMMENT ON COLUMN "public"."t_operation_log"."user_id" IS '操作用户ID';
\ No newline at end of file
diff --git a/web/client/src/app.js b/web/client/src/app.js
index c90edf7..0cbbce7 100644
--- a/web/client/src/app.js
+++ b/web/client/src/app.js
@@ -4,6 +4,8 @@ import React, { useEffect } from 'react';
import Layout from './layout';
import Auth from './sections/auth';
import bigScreen from './sections/bigScreen';
+import Organization from './sections/organization';
+import OperationLog from './sections/operationLogs';
const App = props => {
const { projectName } = props
@@ -15,7 +17,7 @@ const App = props => {
return (