diff --git a/api/app/lib/controllers/auth/index.js b/api/app/lib/controllers/auth/index.js
index b8d6b8e..eb7d901 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) {
// const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
@@ -19,8 +19,7 @@ async function login(ctx, next) {
attributes: { exclude: ['password'] },
where: {
username: params.username,
- password: password,
- enabled: true
+ password: password
},
});
}
@@ -59,7 +58,7 @@ async function login(ctx, next) {
}
}
-async function logout(ctx) {
+async function logout (ctx) {
try {
const models = ctx.fs.dc.models;
const params = ctx.request.body;
diff --git a/api/app/lib/controllers/member/index.js b/api/app/lib/controllers/member/index.js
index b2f8845..3791360 100644
--- a/api/app/lib/controllers/member/index.js
+++ b/api/app/lib/controllers/member/index.js
@@ -1,5 +1,6 @@
'use strict';
-const moment = require('moment')
+const Hex = require('crypto-js/enc-hex');
+const MD5 = require('crypto-js/md5');
function getUserList(opts) {
return async function (ctx, next) {
@@ -17,7 +18,7 @@ function getUserList(opts) {
}
if (name) {
- searchWhere.name = { $like: name };
+ searchWhere.name = { $like: '%' + name + '%' };
}
if (role) {
@@ -25,7 +26,6 @@ function getUserList(opts) {
}
option.where = searchWhere
- let total = await models.User.findAll(option);
let limit_ = limit || 10;
let page_ = page || 1;
let offset = (page_ - 1) * limit_;
@@ -51,14 +51,14 @@ function addUser(opts) {
const models = ctx.fs.dc.models;
try {
- const { attributeName, attributeCode, modelType } = ctx.request.body
- const checkName = await models.User.findOne({ where: { attributeName, modelType } });
- const checkCode = await models.User.findOne({ where: { attributeCode, modelType } });
- if (checkName || checkCode) {
+ const { username } = ctx.request.body
+ const checkName = await models.User.findOne({ where: { username } });
+ if (checkName) {
ctx.status = 400;
- ctx.body = { message: checkName ? '该属性名称已存在' : "该属性代码已存在" }
+ ctx.body = { message: "该用户名已存在" }
} else {
let rslt = ctx.request.body;
+ rslt.password = 'e10adc3949ba59abbe56e057f20f883e';
await models.User.create(Object.assign({}, rslt))
ctx.status = 204;
ctx.body = { message: '新建用户成功' }
@@ -80,21 +80,34 @@ function editUser(opts) {
const models = ctx.fs.dc.models;
const { id } = ctx.params;
const body = ctx.request.body;
- let modelFind = await models.User.findOne({ where: { id: id } });
- const { attributeName, attributeCode } = ctx.request.body;
- const { modelType } = modelFind;
- const checkName = await models.User.findOne({ where: { id: { $not: id }, attributeName, modelType } });
- const checkCode = await models.User.findOne({ where: { id: { $not: id }, attributeCode, modelType } });
- if (checkName || checkCode) {
- ctx.status = 400;
- ctx.body = { message: checkName ? '该属性名称已存在' : "该属性代码已存在" }
+ if (body.oldpassword) {
+ const password = Hex.stringify(MD5(body.oldpassword));
+ const checkPwd = await models.User.findOne({ where: { id: id, password } });
+ if (!checkPwd) {
+ ctx.status = 400;
+ ctx.body = { message: '旧密码错误' }
+ } else {
+ await models.User.update(
+ { password: Hex.stringify(MD5(body.password)) },
+ { where: { id: id, } }
+ )
+ ctx.status = 204;
+ ctx.body = { message: '修改用户成功' }
+ }
} else {
- await models.User.update(
- body,
- { where: { id: id, } }
- )
- ctx.status = 204;
- ctx.body = { message: '修改用户成功' }
+ const checkName = await models.User.findOne({ where: { id: { $not: id }, username: body.username } });
+ if (checkName) {
+ ctx.status = 400;
+ ctx.body = { message: '该用户名已存在' }
+ } else {
+ await models.User.update(
+ body,
+ { where: { id: id, } }
+ )
+ ctx.status = 204;
+ ctx.body = { message: '修改用户成功' }
+ }
+
}
@@ -113,13 +126,23 @@ function deleteUser(opts) {
try {
const models = ctx.fs.dc.models;
const { id } = ctx.params;
- await models.User.destroy({
- where: {
- id: id
- }
- })
- ctx.status = 204;
- ctx.body = { message: '删除用户成功' }
+
+ const checkName1 = await models.MetadataDatabase.findOne({ where: { createBy: id } });
+ const checkName2 = await models.MetadataFile.findOne({ where: { createBy: id } });
+ const checkName3 = await models.MetadataRestapi.findOne({ where: { createBy: id } });
+ if (checkName1 || checkName2 || checkName3) {
+ ctx.status = 400;
+ ctx.body = { message: '该用户下存在依赖资源无法删除!' }
+ } else {
+ await models.User.destroy({
+ where: {
+ id: id
+ }
+ })
+ ctx.status = 204;
+ ctx.body = { message: '删除用户成功' }
+ }
+
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
diff --git a/web/client/src/layout/components/header/index.js b/web/client/src/layout/components/header/index.js
index b397005..85ac40c 100644
--- a/web/client/src/layout/components/header/index.js
+++ b/web/client/src/layout/components/header/index.js
@@ -7,10 +7,23 @@ import styles from './style.css';
import {
MenuFoldOutlined, MenuUnfoldOutlined, UserOutlined, LogoutOutlined
} from '@ant-design/icons';
-
+import ResetPasswordModal from '../../../sections/memberManagement/components/resetPassword';
const Header = props => {
const { dispatch, history, user, pathname, toggleCollapsed, collapsed, actions } = props
+ const onFinish = async (values) => {
+ const dataToSave = { ...values }
+ return dispatch(
+ actions.memberManagement.modifyUser(user.id, dataToSave, values?.msg || ''),
+ ).then((res) => {
+ if (res.success) {
+ return true;
+ } else {
+ return false;
+ }
+ });
+ };
+
const handelClick = item => {
if (item.key == 'logout') {
dispatch(actions.auth.logout(user));
@@ -55,7 +68,18 @@ const Header = props => {
icon: ,
children: [{
label: '退出', key: 'logout'
- }],
+ },
+ {
+ label: 重置密码}
+ title="重置密码"
+ onFinish={onFinish}
+ key="resetPassword"
+ />,
+ key: 'resetPassword'
+ }
+ ],
}]}
/>
@@ -63,7 +87,7 @@ const Header = props => {
);
};
-function mapStateToProps (state) {
+function mapStateToProps(state) {
const { global, auth } = state;
return {
actions: global.actions,
diff --git a/web/client/src/sections/memberManagement/actions/adapter.js b/web/client/src/sections/memberManagement/actions/adapter.js
deleted file mode 100644
index 8dfe530..0000000
--- a/web/client/src/sections/memberManagement/actions/adapter.js
+++ /dev/null
@@ -1,44 +0,0 @@
-'use strict';
-
-import { basicAction } from '@peace/utils'
-import { ApiTable } from '$utils'
-
-export function checkPostgreConnect(params) {
- return (dispatch) => basicAction({
- type: 'post',
- data: params,
- dispatch,
- actionType: 'CHECK_POSTGRE_CONNECT',
- url: ApiTable.pgCheckConnect,
- msg: {
- option: '',
- },
- });
-}
-
-export function addAdapter(params) {
- return (dispatch) => basicAction({
- type: 'post',
- data: params,
- dispatch,
- actionType: 'ADD_ADAPTER',
- url: ApiTable.addAdapter,
- msg: {
- option: '新增适配器',
- },
- });
-}
-
-export function getAdapters(query) {
- return dispatch => basicAction({
- type: 'get',
- dispatch: dispatch,
- query: query || {},
- actionType: 'GET_ACQ_ADAPTERS',
- url: `${ApiTable.getAdapters}`,
- msg: { error: '获取适配器列表失败' },
- reducer: { name: 'adapters' }
- });
-}
-
-
diff --git a/web/client/src/sections/memberManagement/actions/dataSource.js b/web/client/src/sections/memberManagement/actions/dataSource.js
deleted file mode 100644
index 91f8963..0000000
--- a/web/client/src/sections/memberManagement/actions/dataSource.js
+++ /dev/null
@@ -1,56 +0,0 @@
-'use strict';
-
-import { basicAction } from '@peace/utils'
-import { ApiTable } from '$utils'
-
-export function addDataSource(params, msg) {
- return (dispatch) => basicAction({
- type: 'post',
- data: params,
- dispatch,
- actionType: 'ADD_DATSOURCE',
- url: ApiTable.addDataSource,
- msg: {
- option: msg == '' ? '' : '新增数据源',
- },
- });
-}
-
-export function getDataSources(query) {
- return dispatch => basicAction({
- type: 'get',
- dispatch: dispatch,
- query: query || {},
- actionType: 'GET_ACQ_DATASOURCES',
- url: `${ApiTable.getDataSources}`,
- msg: { error: '获取数据源列表失败' },
- reducer: { name: 'datasources' }
- });
-}
-
-export function deleteDataSource(id) {
- return (dispatch) => basicAction({
- type: 'del',
- dispatch,
- actionType: 'DELETE_ACQ_DATASOURCE',
- url: ApiTable.modifyDataSource.replace('{id}', id),
- msg: {
- option: '数据源删除',
- },
- });
-}
-
-export function modifyDataSource(id, params, msg) {
- return (dispatch) => basicAction({
- type: 'put',
- data: params,
- dispatch,
- actionType: 'MODIFY_ACQ_DATASOURCE',
- url: ApiTable.modifyDataSource.replace('{id}', id),
- msg: {
- option: msg || '数据源编辑',
- },
- });
-}
-
-
diff --git a/web/client/src/sections/memberManagement/actions/example.js b/web/client/src/sections/memberManagement/actions/example.js
deleted file mode 100644
index 6b3c25d..0000000
--- a/web/client/src/sections/memberManagement/actions/example.js
+++ /dev/null
@@ -1,15 +0,0 @@
-'use strict';
-
-import { basicAction } from '@peace/utils'
-import { ApiTable } from '$utils'
-
-// export function getMembers(orgId) {
-// return dispatch => basicAction({
-// type: 'get',
-// dispatch: dispatch,
-// actionType: 'GET_MEMBERS',
-// url: `${ApiTable.getEnterprisesMembers.replace('{enterpriseId}', orgId)}`,
-// msg: { error: '获取用户列表失败' },
-// reducer: { name: 'members' }
-// });
-// }
diff --git a/web/client/src/sections/memberManagement/actions/index.js b/web/client/src/sections/memberManagement/actions/index.js
index c419cad..5abd7d2 100644
--- a/web/client/src/sections/memberManagement/actions/index.js
+++ b/web/client/src/sections/memberManagement/actions/index.js
@@ -1,14 +1,6 @@
'use strict';
-import * as example from './example'
-import * as adapter from './adapter'
-import * as dataSource from './dataSource'
-import * as task from './task';
-import * as log from './log';
+import * as member from './member';
export default {
- ...example,
- ...adapter,
- ...dataSource,
- ...task,
- ...log
+ ...member
}
\ No newline at end of file
diff --git a/web/client/src/sections/memberManagement/actions/log.js b/web/client/src/sections/memberManagement/actions/log.js
deleted file mode 100644
index 0fba54a..0000000
--- a/web/client/src/sections/memberManagement/actions/log.js
+++ /dev/null
@@ -1,16 +0,0 @@
-'use strict';
-
-import { basicAction } from '@peace/utils'
-import { ApiTable } from '$utils'
-
-export function getLogs(query) {
- return dispatch => basicAction({
- type: 'get',
- dispatch: dispatch,
- query: query || {},
- actionType: 'GET_ACQ_LOGS',
- url: `${ApiTable.getLogs}`,
- msg: { error: '获取采集日志失败' },
- reducer: { name: 'acqlogs' }
- });
-}
\ No newline at end of file
diff --git a/web/client/src/sections/memberManagement/actions/member.js b/web/client/src/sections/memberManagement/actions/member.js
new file mode 100644
index 0000000..ec6ab27
--- /dev/null
+++ b/web/client/src/sections/memberManagement/actions/member.js
@@ -0,0 +1,56 @@
+'use strict';
+
+import { basicAction } from '@peace/utils'
+import { ApiTable } from '$utils'
+
+export function getUserList(query) {
+ return dispatch => basicAction({
+ type: 'get',
+ dispatch: dispatch,
+ query: query || {},
+ actionType: 'GET_MEMBER_REPORT',
+ url: `${ApiTable.getUserList}`,
+ msg: { error: '获取用户列表失败' },
+ reducer: { name: 'member' }
+ });
+}
+
+
+export function addUser(params) {
+ return (dispatch) => basicAction({
+ type: 'post',
+ data: params,
+ dispatch,
+ actionType: 'ADD_MEMBER_REPORT',
+ url: ApiTable.addUser,
+ msg: {
+ option: '用户新增',
+ },
+ });
+}
+
+export function deleteUser(id) {
+ return (dispatch) => basicAction({
+ type: 'del',
+ dispatch,
+ actionType: 'DELETE_MEMBER_REPORT',
+ url: ApiTable.modifyUser.replace('{id}', id),
+ msg: {
+ option: '用户删除',
+ },
+ });
+}
+
+export function modifyUser(id, params, msg) {
+ return (dispatch) => basicAction({
+ type: 'put',
+ data: params,
+ dispatch,
+ actionType: 'MODIFY_MEMBER_REPORT',
+ url: ApiTable.modifyUser.replace('{id}', id),
+ msg: {
+ option: msg || '用户编辑',
+ },
+ });
+}
+
diff --git a/web/client/src/sections/memberManagement/components/memberModal.js b/web/client/src/sections/memberManagement/components/memberModal.js
index 6522f60..e2e7a26 100644
--- a/web/client/src/sections/memberManagement/components/memberModal.js
+++ b/web/client/src/sections/memberManagement/components/memberModal.js
@@ -58,6 +58,7 @@ export default (props) => {
/>
{
label="角色"
/>
-
+
);
};
\ No newline at end of file
diff --git a/web/client/src/sections/memberManagement/components/resetPassword.js b/web/client/src/sections/memberManagement/components/resetPassword.js
new file mode 100644
index 0000000..ce4dfdc
--- /dev/null
+++ b/web/client/src/sections/memberManagement/components/resetPassword.js
@@ -0,0 +1,61 @@
+import React, { useRef } from 'react';
+import { Button, Form } from 'antd';
+import {
+ ModalForm,
+ ProFormText,
+} from '@ant-design/pro-form';
+
+export default (props) => {
+ const { title, triggerRender, editData = null, onFinish } = props;
+ const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 16 } };
+ const initialValues = {};
+ const [form] = Form.useForm();
+ const formRef = useRef();
+ return (
+
+ {title || ''}
+
+ }
+ layout="horizontal"
+ grid={true}
+ {...formItemLayout}
+ modalProps={{
+ destroyOnClose: true,
+ onCancel: () => { },
+ }}
+ onFinish={async (values) => {
+ return onFinish && await onFinish({ ...values, msg: '重置密码' }, editData, '重置密码')
+ }}
+ width={500}
+ >
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/web/client/src/sections/memberManagement/containers/member.js b/web/client/src/sections/memberManagement/containers/member.js
index bbd00a6..fb64dba 100644
--- a/web/client/src/sections/memberManagement/containers/member.js
+++ b/web/client/src/sections/memberManagement/containers/member.js
@@ -4,10 +4,11 @@ import { connect } from 'react-redux';
import ProTable from '@ant-design/pro-table';
import moment from 'moment';
import MemberModal from '../components/memberModal';
+import ResetPasswordModal from '../components/resetPassword';
import { useFsRequest, ApiTable } from '$utils';
import './style.less';
function Member(props) {
- const { loading, clientHeight, actions, dispatch, dataSources, adapters } = props;
+ const { loading, clientHeight, actions, dispatch, member } = props;
const [pageSize, setPageSize] = useState(10);
const [currentPage, setCurrentPage] = useState(1);
const [searchValue, setSearchValue] = useState('')
@@ -19,10 +20,11 @@ function Member(props) {
const query = {
limit: search ? 10 : pageSize || 10,
page: search ? 1 : currentPage || 1,
- name: searchValue
+ name: searchValue,
+ role: searchRole
}
- dispatch(actions.metadataAcquisition.getDataSources(query));
+ dispatch(actions.memberManagement.getUserList(query));
}
const { data: treeData = [] } = useFsRequest({
url: ApiTable.getResourceCatalog,
@@ -30,16 +32,9 @@ function Member(props) {
});
useEffect(() => {
- dispatch(actions.metadataAcquisition.getAdapters())
queryData();
}, [pageSize, currentPage]);
- const handleDelete = (id) => {
- dispatch(actions.metadataAcquisition.deleteDataSource(id)).then(() => {
- queryData();
- });
- };
-
const columns = [
{
title: '序号',
@@ -61,6 +56,9 @@ function Member(props) {
{
title: '状态',
dataIndex: 'enabled',
+ render: (text, record) => {
+ return ● {record?.enabled ? '正常' : '禁用'}
+ }
},
{
title: '操作',
@@ -69,65 +67,71 @@ function Member(props) {
valueType: 'option',
render: (text, record) => {
const options = [];
- options.push( {
- setVisible(true)
- setEditData(record)
- }} style={{ marginRight: 8 }}>编辑)
+ options.push(编辑}
+ title="编辑用户"
+ onFinish={onFinish}
+ key="editUser"
+ />)
options.push(
是否确认删除该数据源?
- (将同步删除数据源下的元数据)
>}
+ title={<>是否确认删除该用户?
+ >}
onConfirm={() => handleDelete(record.id)}
okText="是"
cancelText="否"
>
删除
)
+ options.push(重置密码}
+ title="重置密码"
+ onFinish={onFinish}
+ key="resetPassword"
+ />)
+
return options;
},
},
];
- const onFinish = (values) => {
- const { stepOneValues, stepTwoValues, } = values;
- const adapterInfo = adapters?.find(x => x.adapterName == stepOneValues?.adapterName)
- if (adapterInfo) {
- const dataToSave = {
- name: stepOneValues?.name,
- audited: true,
- adapterId: adapterInfo?.id,
- mountPath: stepOneValues?.mountPath,
- catalogKey: stepOneValues?.catalogKey,
- description: stepOneValues?.description,
- config: stepTwoValues,
- time: moment()
- }
- if (editData) {
- dispatch(actions.metadataAcquisition.modifyDataSource(editData?.id, dataToSave)).then(res => {
- if (res.success) {
- setVisible(false);
- setEditData(null);
- queryData();
- }
- })
+ const handleDelete = (id) => {
+ dispatch(actions.memberManagement.deleteUser(id)).then(() => {
+ queryData();
+ });
+ };
+
+ const onFinish = async (values, editData) => {
+ if (editData) {
+ const dataToSave = { ...values }
+ return dispatch(
+ actions.memberManagement.modifyUser(editData.id, dataToSave, values?.msg || ''),
+ ).then((res) => {
+ if (res.success) {
+ queryData();
+ return true;
+ } else {
+ return false;
+ }
+ });
+ }
+
+ return dispatch(actions.memberManagement.addUser({
+ ...values,
+ })).then(res => {
+ if (res.success) {
+ queryData();
+ return true;
} else {
- dispatch(actions.metadataAcquisition.addDataSource(dataToSave)).then(res => {
- if (res.success) {
- setVisible(false);
- setEditData(null);
- queryData();
- }
- })
+ return false;
}
- }
- }
- const refresh = () => {
- // queryData();
- setRefreshTree(refreshTree + 1)
- }
+ });
+ };
return
@@ -145,6 +149,7 @@ function Member(props) {
style={{ width: 220, marginRight: 15 }} placeholder="请输入" />
角色:
@@ -201,14 +206,13 @@ function Member(props) {
function mapStateToProps(state) {
const {
- auth, global, datasources, adapters
+ auth, global, datasources, member
} = state;
return {
- loading: datasources.isRequesting || adapters?.isRequesting,
+ loading: datasources.isRequesting,
clientHeight: global.clientHeight,
actions: global.actions,
- dataSources: datasources?.data || {},
- adapters: adapters?.data || []
+ member: member?.data || {},
};
}
diff --git a/web/client/src/sections/memberManagement/index.js b/web/client/src/sections/memberManagement/index.js
index ef51db2..b83db00 100644
--- a/web/client/src/sections/memberManagement/index.js
+++ b/web/client/src/sections/memberManagement/index.js
@@ -7,7 +7,7 @@ import { getNavItem } from './nav-item';
export default {
key: 'memberManagement',
- name: '元数据采集',
+ name: '用户管理',
reducers: reducers,
routes: routes,
actions: actions,
diff --git a/web/client/src/sections/memberManagement/nav-item.js b/web/client/src/sections/memberManagement/nav-item.js
index 520cbdb..1615180 100644
--- a/web/client/src/sections/memberManagement/nav-item.js
+++ b/web/client/src/sections/memberManagement/nav-item.js
@@ -4,12 +4,14 @@ import { Menu } from 'antd';
import { BarChartOutlined } from '@ant-design/icons';
const SubMenu = Menu.SubMenu;
-export function getNavItem() {
+export function getNavItem(user) {
+
return (
- } title='用户管理'>
+ user?.role == '系统管理员' && } title='用户管理'>
用户权限
SubMenu >
- );
+ )
+
}
\ No newline at end of file
diff --git a/web/client/src/sections/memberManagement/routes.js b/web/client/src/sections/memberManagement/routes.js
index ac7ff7e..0888966 100644
--- a/web/client/src/sections/memberManagement/routes.js
+++ b/web/client/src/sections/memberManagement/routes.js
@@ -5,7 +5,7 @@ export default [{
route: {
path: '/memberManagement',
key: 'memberManagement',
- breadcrumb: '元数据采集',
+ breadcrumb: '用户管理',
// 不设置 component 则面包屑禁止跳转
childRoutes: [{
path: '/auth',
diff --git a/web/client/src/utils/webapi.js b/web/client/src/utils/webapi.js
index cbe1891..d90217e 100644
--- a/web/client/src/utils/webapi.js
+++ b/web/client/src/utils/webapi.js
@@ -73,7 +73,12 @@ export const ApiTable = {
runTask: 'run/acq/task',
//采集日志
- getLogs: "meta/acq/logs"
+ getLogs: "meta/acq/logs",
+
+ //用户管理
+ getUserList: 'meta/members',
+ addUser: 'meta/member',
+ modifyUser: 'meta/member/{id}',
};
export const RouteTable = {