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="请输入" /> 角色: