mirror of https://github.com/veops/cmdb.git
Merge branch 'master' into doc
This commit is contained in:
commit
42d20e5397
|
@ -26,6 +26,7 @@ Flask-Bcrypt = "==1.0.1"
|
||||||
Flask-Cors = ">=3.0.8"
|
Flask-Cors = ">=3.0.8"
|
||||||
ldap3 = "==2.9.1"
|
ldap3 = "==2.9.1"
|
||||||
pycryptodome = "==3.12.0"
|
pycryptodome = "==3.12.0"
|
||||||
|
cryptography = "==41.0.2"
|
||||||
# Caching
|
# Caching
|
||||||
Flask-Caching = ">=1.0.0"
|
Flask-Caching = ">=1.0.0"
|
||||||
# Environment variable parsing
|
# Environment variable parsing
|
||||||
|
|
|
@ -216,10 +216,9 @@ class InitDepartment(object):
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
app = acl.validate_app()
|
app = acl.validate_app()
|
||||||
if app:
|
if not app:
|
||||||
return acl
|
acl.create_app(payload)
|
||||||
|
return acl
|
||||||
acl.create_app(payload)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
current_app.logger.error(e)
|
current_app.logger.error(e)
|
||||||
if '不存在' in str(e):
|
if '不存在' in str(e):
|
||||||
|
|
|
@ -60,22 +60,33 @@ class AttributeManager(object):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_choice_values_from_other_ci(choice_other):
|
def _get_choice_values_from_other(choice_other):
|
||||||
from api.lib.cmdb.search import SearchError
|
from api.lib.cmdb.search import SearchError
|
||||||
from api.lib.cmdb.search.ci import search
|
from api.lib.cmdb.search.ci import search
|
||||||
|
|
||||||
type_ids = choice_other.get('type_ids')
|
if choice_other.get('type_ids'):
|
||||||
attr_id = choice_other.get('attr_id')
|
type_ids = choice_other.get('type_ids')
|
||||||
other_filter = choice_other.get('filter') or ''
|
attr_id = choice_other.get('attr_id')
|
||||||
|
other_filter = choice_other.get('filter') or ''
|
||||||
|
|
||||||
query = "_type:({}),{}".format(";".join(map(str, type_ids)), other_filter)
|
query = "_type:({}),{}".format(";".join(map(str, type_ids)), other_filter)
|
||||||
s = search(query, fl=[str(attr_id)], facet=[str(attr_id)], count=1)
|
s = search(query, fl=[str(attr_id)], facet=[str(attr_id)], count=1)
|
||||||
try:
|
try:
|
||||||
_, _, _, _, _, facet = s.search()
|
_, _, _, _, _, facet = s.search()
|
||||||
return [[i[0], {}] for i in (list(facet.values()) or [[]])[0]]
|
return [[i[0], {}] for i in (list(facet.values()) or [[]])[0]]
|
||||||
except SearchError as e:
|
except SearchError as e:
|
||||||
current_app.logger.error("get choice values from other ci failed: {}".format(e))
|
current_app.logger.error("get choice values from other ci failed: {}".format(e))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
elif choice_other.get('script'):
|
||||||
|
try:
|
||||||
|
x = compile(choice_other['script'], '', "exec")
|
||||||
|
exec(x)
|
||||||
|
res = locals()['ChoiceValue']().values() or []
|
||||||
|
return [[i, {}] for i in res]
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.error("get choice values from script: {}".format(e))
|
||||||
|
return []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_choice_values(cls, attr_id, value_type, choice_web_hook, choice_other,
|
def get_choice_values(cls, attr_id, value_type, choice_web_hook, choice_other,
|
||||||
|
@ -87,7 +98,7 @@ class AttributeManager(object):
|
||||||
return []
|
return []
|
||||||
elif choice_other:
|
elif choice_other:
|
||||||
if choice_other_parse and isinstance(choice_other, dict):
|
if choice_other_parse and isinstance(choice_other, dict):
|
||||||
return cls._get_choice_values_from_other_ci(choice_other)
|
return cls._get_choice_values_from_other(choice_other)
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -96,7 +107,8 @@ class AttributeManager(object):
|
||||||
return []
|
return []
|
||||||
choice_values = choice_table.get_by(fl=["value", "option"], attr_id=attr_id)
|
choice_values = choice_table.get_by(fl=["value", "option"], attr_id=attr_id)
|
||||||
|
|
||||||
return [[choice_value['value'], choice_value['option']] for choice_value in choice_values]
|
return [[ValueTypeMap.serialize[value_type](choice_value['value']), choice_value['option']]
|
||||||
|
for choice_value in choice_values]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_choice_values(_id, value_type, choice_values):
|
def add_choice_values(_id, value_type, choice_values):
|
||||||
|
@ -218,10 +230,15 @@ class AttributeManager(object):
|
||||||
if name in BUILTIN_KEYWORDS:
|
if name in BUILTIN_KEYWORDS:
|
||||||
return abort(400, ErrFormat.attribute_name_cannot_be_builtin)
|
return abort(400, ErrFormat.attribute_name_cannot_be_builtin)
|
||||||
|
|
||||||
if kwargs.get('choice_other'):
|
while kwargs.get('choice_other'):
|
||||||
if (not isinstance(kwargs['choice_other'], dict) or not kwargs['choice_other'].get('type_ids') or
|
if isinstance(kwargs['choice_other'], dict):
|
||||||
not kwargs['choice_other'].get('attr_id')):
|
if kwargs['choice_other'].get('script'):
|
||||||
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
break
|
||||||
|
|
||||||
|
if kwargs['choice_other'].get('type_ids') and kwargs['choice_other'].get('attr_id'):
|
||||||
|
break
|
||||||
|
|
||||||
|
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
||||||
|
|
||||||
alias = kwargs.pop("alias", "")
|
alias = kwargs.pop("alias", "")
|
||||||
alias = name if not alias else alias
|
alias = name if not alias else alias
|
||||||
|
@ -232,6 +249,8 @@ class AttributeManager(object):
|
||||||
|
|
||||||
kwargs.get('is_computed') and cls.can_create_computed_attribute()
|
kwargs.get('is_computed') and cls.can_create_computed_attribute()
|
||||||
|
|
||||||
|
kwargs.get('choice_other') and kwargs['choice_other'].get('script') and cls.can_create_computed_attribute()
|
||||||
|
|
||||||
attr = Attribute.create(flush=True,
|
attr = Attribute.create(flush=True,
|
||||||
name=name,
|
name=name,
|
||||||
alias=alias,
|
alias=alias,
|
||||||
|
@ -337,10 +356,15 @@ class AttributeManager(object):
|
||||||
|
|
||||||
self._change_index(attr, attr.is_index, kwargs['is_index'])
|
self._change_index(attr, attr.is_index, kwargs['is_index'])
|
||||||
|
|
||||||
if kwargs.get('choice_other'):
|
while kwargs.get('choice_other'):
|
||||||
if (not isinstance(kwargs['choice_other'], dict) or not kwargs['choice_other'].get('type_ids') or
|
if isinstance(kwargs['choice_other'], dict):
|
||||||
not kwargs['choice_other'].get('attr_id')):
|
if kwargs['choice_other'].get('script'):
|
||||||
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
break
|
||||||
|
|
||||||
|
if kwargs['choice_other'].get('type_ids') and kwargs['choice_other'].get('attr_id'):
|
||||||
|
break
|
||||||
|
|
||||||
|
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
||||||
|
|
||||||
existed2 = attr.to_dict()
|
existed2 = attr.to_dict()
|
||||||
if not existed2['choice_web_hook'] and not existed2.get('choice_other') and existed2['is_choice']:
|
if not existed2['choice_web_hook'] and not existed2.get('choice_other') and existed2['is_choice']:
|
||||||
|
|
|
@ -28,6 +28,7 @@ from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_NO_ATTR
|
||||||
from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_TYPE
|
from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_TYPE
|
||||||
from api.lib.cmdb.search.ci.db.query_sql import QUERY_UNION_CI_ATTRIBUTE_IS_NULL
|
from api.lib.cmdb.search.ci.db.query_sql import QUERY_UNION_CI_ATTRIBUTE_IS_NULL
|
||||||
from api.lib.cmdb.utils import TableMap
|
from api.lib.cmdb.utils import TableMap
|
||||||
|
from api.lib.cmdb.utils import ValueTypeMap
|
||||||
from api.lib.perm.acl.acl import ACLManager
|
from api.lib.perm.acl.acl import ACLManager
|
||||||
from api.lib.perm.acl.acl import is_app_admin
|
from api.lib.perm.acl.acl import is_app_admin
|
||||||
from api.lib.utils import handle_arg_list
|
from api.lib.utils import handle_arg_list
|
||||||
|
@ -524,15 +525,15 @@ class Search(object):
|
||||||
if k:
|
if k:
|
||||||
table_name = TableMap(attr=attr).table_name
|
table_name = TableMap(attr=attr).table_name
|
||||||
query_sql = FACET_QUERY.format(table_name, self.query_sql, attr.id)
|
query_sql = FACET_QUERY.format(table_name, self.query_sql, attr.id)
|
||||||
# current_app.logger.warning(query_sql)
|
|
||||||
result = db.session.execute(query_sql).fetchall()
|
result = db.session.execute(query_sql).fetchall()
|
||||||
facet[k] = result
|
facet[k] = result
|
||||||
|
|
||||||
facet_result = dict()
|
facet_result = dict()
|
||||||
for k, v in facet.items():
|
for k, v in facet.items():
|
||||||
if not k.startswith('_'):
|
if not k.startswith('_'):
|
||||||
a = getattr(AttributeCache.get(k), self.ret_key)
|
attr = AttributeCache.get(k)
|
||||||
facet_result[a] = [(f[0], f[1], a) for f in v]
|
a = getattr(attr, self.ret_key)
|
||||||
|
facet_result[a] = [(ValueTypeMap.serialize[attr.value_type](f[0]), f[1], a) for f in v]
|
||||||
|
|
||||||
return facet_result
|
return facet_result
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import api.models.cmdb as model
|
||||||
from api.lib.cmdb.cache import AttributeCache
|
from api.lib.cmdb.cache import AttributeCache
|
||||||
from api.lib.cmdb.const import ValueTypeEnum
|
from api.lib.cmdb.const import ValueTypeEnum
|
||||||
|
|
||||||
TIME_RE = re.compile(r"^(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$")
|
TIME_RE = re.compile(r"^20|21|22|23|[0-1]\d:[0-5]\d:[0-5]\d$")
|
||||||
|
|
||||||
|
|
||||||
def string2int(x):
|
def string2int(x):
|
||||||
|
@ -21,7 +21,7 @@ def string2int(x):
|
||||||
|
|
||||||
def str2datetime(x):
|
def str2datetime(x):
|
||||||
try:
|
try:
|
||||||
return datetime.datetime.strptime(x, "%Y-%m-%d")
|
return datetime.datetime.strptime(x, "%Y-%m-%d").date()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ class ValueTypeMap(object):
|
||||||
ValueTypeEnum.FLOAT: float,
|
ValueTypeEnum.FLOAT: float,
|
||||||
ValueTypeEnum.TEXT: lambda x: x if isinstance(x, six.string_types) else str(x),
|
ValueTypeEnum.TEXT: lambda x: x if isinstance(x, six.string_types) else str(x),
|
||||||
ValueTypeEnum.TIME: lambda x: x if isinstance(x, six.string_types) else str(x),
|
ValueTypeEnum.TIME: lambda x: x if isinstance(x, six.string_types) else str(x),
|
||||||
ValueTypeEnum.DATE: lambda x: x.strftime("%Y-%m-%d"),
|
ValueTypeEnum.DATE: lambda x: x.strftime("%Y-%m-%d") if not isinstance(x, six.string_types) else x,
|
||||||
ValueTypeEnum.DATETIME: lambda x: x.strftime("%Y-%m-%d %H:%M:%S"),
|
ValueTypeEnum.DATETIME: lambda x: x.strftime("%Y-%m-%d %H:%M:%S") if not isinstance(x, six.string_types) else x,
|
||||||
ValueTypeEnum.JSON: lambda x: json.loads(x) if isinstance(x, six.string_types) and x else x,
|
ValueTypeEnum.JSON: lambda x: json.loads(x) if isinstance(x, six.string_types) and x else x,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@ class ValueTypeMap(object):
|
||||||
ValueTypeEnum.FLOAT: model.FloatChoice,
|
ValueTypeEnum.FLOAT: model.FloatChoice,
|
||||||
ValueTypeEnum.TEXT: model.TextChoice,
|
ValueTypeEnum.TEXT: model.TextChoice,
|
||||||
ValueTypeEnum.TIME: model.TextChoice,
|
ValueTypeEnum.TIME: model.TextChoice,
|
||||||
|
ValueTypeEnum.DATE: model.TextChoice,
|
||||||
|
ValueTypeEnum.DATETIME: model.TextChoice,
|
||||||
}
|
}
|
||||||
|
|
||||||
table = {
|
table = {
|
||||||
|
@ -97,7 +99,7 @@ class ValueTypeMap(object):
|
||||||
ValueTypeEnum.DATE: 'text',
|
ValueTypeEnum.DATE: 'text',
|
||||||
ValueTypeEnum.TIME: 'text',
|
ValueTypeEnum.TIME: 'text',
|
||||||
ValueTypeEnum.FLOAT: 'float',
|
ValueTypeEnum.FLOAT: 'float',
|
||||||
ValueTypeEnum.JSON: 'object'
|
ValueTypeEnum.JSON: 'object',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
from flask import abort
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
from api.lib.common_setting.resp_format import ErrFormat
|
from api.lib.common_setting.resp_format import ErrFormat
|
||||||
|
from api.lib.perm.acl.app import AppCRUD
|
||||||
from api.lib.perm.acl.cache import RoleCache, AppCache
|
from api.lib.perm.acl.cache import RoleCache, AppCache
|
||||||
|
from api.lib.perm.acl.permission import PermissionCRUD
|
||||||
|
from api.lib.perm.acl.resource import ResourceTypeCRUD, ResourceCRUD
|
||||||
from api.lib.perm.acl.role import RoleCRUD, RoleRelationCRUD
|
from api.lib.perm.acl.role import RoleCRUD, RoleRelationCRUD
|
||||||
from api.lib.perm.acl.user import UserCRUD
|
from api.lib.perm.acl.user import UserCRUD
|
||||||
from api.lib.perm.acl.resource import ResourceTypeCRUD, ResourceCRUD
|
|
||||||
from api.lib.perm.acl.permission import PermissionCRUD
|
|
||||||
|
|
||||||
|
|
||||||
class ACLManager(object):
|
class ACLManager(object):
|
||||||
|
@ -133,3 +133,9 @@ class ACLManager(object):
|
||||||
|
|
||||||
def grant_resource(self, rid, resource_id, perms):
|
def grant_resource(self, rid, resource_id, perms):
|
||||||
PermissionCRUD.grant(rid, perms, resource_id=resource_id, group_id=None)
|
PermissionCRUD.grant(rid, perms, resource_id=resource_id, group_id=None)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_app(payload):
|
||||||
|
rt = AppCRUD.add(**payload)
|
||||||
|
|
||||||
|
return rt.to_dict()
|
||||||
|
|
|
@ -121,6 +121,19 @@ class EmployeeCRUD(object):
|
||||||
employee = CreateEmployee().create_single(**data)
|
employee = CreateEmployee().create_single(**data)
|
||||||
return employee.to_dict()
|
return employee.to_dict()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_employee_from_acl_created(**kwargs):
|
||||||
|
try:
|
||||||
|
kwargs['acl_uid'] = kwargs.pop('uid')
|
||||||
|
kwargs['acl_rid'] = kwargs.pop('rid')
|
||||||
|
kwargs['department_id'] = 0
|
||||||
|
|
||||||
|
Employee.create(
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
abort(400, str(e))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add(**kwargs):
|
def add(**kwargs):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -8,6 +8,7 @@ from flask import current_app
|
||||||
from flask import request
|
from flask import request
|
||||||
from sqlalchemy.exc import InvalidRequestError
|
from sqlalchemy.exc import InvalidRequestError
|
||||||
from sqlalchemy.exc import OperationalError
|
from sqlalchemy.exc import OperationalError
|
||||||
|
from sqlalchemy.exc import PendingRollbackError
|
||||||
from sqlalchemy.exc import StatementError
|
from sqlalchemy.exc import StatementError
|
||||||
|
|
||||||
from api.extensions import db
|
from api.extensions import db
|
||||||
|
@ -98,7 +99,10 @@ def reconnect_db(func):
|
||||||
|
|
||||||
|
|
||||||
def _flush_db():
|
def _flush_db():
|
||||||
db.session.commit()
|
try:
|
||||||
|
db.session.commit()
|
||||||
|
except (StatementError, OperationalError, InvalidRequestError, PendingRollbackError):
|
||||||
|
db.session.rollback()
|
||||||
|
|
||||||
|
|
||||||
def flush_db(func):
|
def flush_db(func):
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import msgpack
|
import msgpack
|
||||||
|
|
||||||
from api.extensions import cache
|
from api.extensions import cache
|
||||||
from api.extensions import db
|
from api.lib.decorator import flush_db
|
||||||
from api.lib.utils import Lock
|
from api.lib.utils import Lock
|
||||||
from api.models.acl import App
|
from api.models.acl import App
|
||||||
from api.models.acl import Permission
|
from api.models.acl import Permission
|
||||||
|
@ -221,9 +221,9 @@ class RoleRelationCache(object):
|
||||||
return msgpack.loads(r_g, raw=False)
|
return msgpack.loads(r_g, raw=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@flush_db
|
||||||
def rebuild(cls, rid, app_id):
|
def rebuild(cls, rid, app_id):
|
||||||
cls.clean(rid, app_id)
|
cls.clean(rid, app_id)
|
||||||
db.session.remove()
|
|
||||||
|
|
||||||
cls.get_parent_ids(rid, app_id)
|
cls.get_parent_ids(rid, app_id)
|
||||||
cls.get_child_ids(rid, app_id)
|
cls.get_child_ids(rid, app_id)
|
||||||
|
@ -235,9 +235,9 @@ class RoleRelationCache(object):
|
||||||
cls.get_resources2(rid, app_id)
|
cls.get_resources2(rid, app_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@flush_db
|
||||||
def rebuild2(cls, rid, app_id):
|
def rebuild2(cls, rid, app_id):
|
||||||
cache.delete(cls.PREFIX_RESOURCES2.format(rid, app_id))
|
cache.delete(cls.PREFIX_RESOURCES2.format(rid, app_id))
|
||||||
db.session.remove()
|
|
||||||
cls.get_resources2(rid, app_id)
|
cls.get_resources2(rid, app_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -58,10 +58,14 @@ class UserCRUD(object):
|
||||||
kwargs['employee_id'] = '{0:04d}'.format(biggest_employee_id + 1)
|
kwargs['employee_id'] = '{0:04d}'.format(biggest_employee_id + 1)
|
||||||
user = User.create(**kwargs)
|
user = User.create(**kwargs)
|
||||||
|
|
||||||
RoleCRUD.add_role(user.username, uid=user.uid)
|
role = RoleCRUD.add_role(user.username, uid=user.uid)
|
||||||
AuditCRUD.add_role_log(None, AuditOperateType.create,
|
AuditCRUD.add_role_log(None, AuditOperateType.create,
|
||||||
AuditScope.user, user.uid, {}, user.to_dict(), {}, {}
|
AuditScope.user, user.uid, {}, user.to_dict(), {}, {}
|
||||||
)
|
)
|
||||||
|
from api.lib.common_setting.employee import EmployeeCRUD
|
||||||
|
payload = {column: getattr(user, column) for column in ['uid', 'username', 'nickname', 'email', 'block']}
|
||||||
|
payload['rid'] = role.id
|
||||||
|
EmployeeCRUD.add_employee_from_acl_created(**payload)
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,8 @@ class UserQuery(BaseQuery):
|
||||||
|
|
||||||
conn = Connection(server, user=who, password=password)
|
conn = Connection(server, user=who, password=password)
|
||||||
conn.bind()
|
conn.bind()
|
||||||
|
if conn.result['result'] != 0:
|
||||||
|
raise LDAPBindError
|
||||||
conn.unbind()
|
conn.unbind()
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
|
|
|
@ -30,6 +30,7 @@ more-itertools==5.0.0
|
||||||
msgpack-python==0.5.6
|
msgpack-python==0.5.6
|
||||||
Pillow==9.3.0
|
Pillow==9.3.0
|
||||||
pycryptodome==3.12.0
|
pycryptodome==3.12.0
|
||||||
|
cryptography==41.0.2
|
||||||
PyJWT==2.4.0
|
PyJWT==2.4.0
|
||||||
PyMySQL==1.1.0
|
PyMySQL==1.1.0
|
||||||
ldap3==2.9.1
|
ldap3==2.9.1
|
||||||
|
|
|
@ -1,194 +1,198 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="acl-users">
|
<div class="acl-users">
|
||||||
<div class="acl-users-header">
|
<div class="acl-users-header">
|
||||||
<a-button v-if="isAclAdmin" @click="handleCreate" type="primary">{{ btnName }}</a-button>
|
<a-button v-if="isAclAdmin" @click="handleCreate" type="primary">{{ btnName }}</a-button>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
class="ops-input"
|
class="ops-input"
|
||||||
allowClear
|
allowClear
|
||||||
:style="{ display: 'inline', marginLeft: '10px' }"
|
:style="{ display: 'inline', marginLeft: '10px' }"
|
||||||
placeholder="搜索 | 用户名、中文名"
|
placeholder="搜索 | 用户名、中文名"
|
||||||
v-model="searchName"
|
v-model="searchName"
|
||||||
></a-input-search>
|
></a-input-search>
|
||||||
</div>
|
</div>
|
||||||
<a-spin :spinning="loading">
|
<a-spin :spinning="loading">
|
||||||
<vxe-grid
|
<vxe-grid
|
||||||
stripe
|
stripe
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
:columns="tableColumns"
|
:columns="tableColumns"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
show-overflow
|
show-overflow
|
||||||
highlight-hover-row
|
highlight-hover-row
|
||||||
:height="`${windowHeight - 165}px`"
|
:height="`${windowHeight - 165}px`"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
<template #block_default="{row}">
|
<template #block_default="{row}">
|
||||||
<a-icon type="lock" v-if="row.block" />
|
<a-icon type="lock" v-if="row.block" />
|
||||||
</template>
|
</template>
|
||||||
<template #action_default="{row}">
|
<template #action_default="{row}">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a :disabled="isAclAdmin ? false : true" @click="handleEdit(row)">
|
<a :disabled="isAclAdmin ? false : true" @click="handleEdit(row)">
|
||||||
<a-icon type="edit" />
|
<a-icon type="edit" />
|
||||||
</a>
|
</a>
|
||||||
<a-tooltip title="权限汇总">
|
<a-tooltip title="权限汇总">
|
||||||
<a @click="handlePermCollect(row)"><a-icon type="solution"/></a>
|
<a @click="handlePermCollect(row)"><a-icon type="solution"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-popconfirm :title="`确认删除【${row.nickname || row.username}】?`" @confirm="deleteUser(row.uid)">
|
<a-popconfirm :title="`确认删除【${row.nickname || row.username}】?`" @confirm="deleteUser(row.uid)">
|
||||||
<a :style="{ color: 'red' }"><ops-icon type="icon-xianxing-delete"/></a>
|
<a :style="{ color: 'red' }"><ops-icon type="icon-xianxing-delete"/></a>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
</vxe-grid>
|
</vxe-grid>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
<userForm ref="userForm" :handleOk="handleOk"> </userForm>
|
<userForm ref="userForm" :handleOk="handleOk"> </userForm>
|
||||||
<perm-collect-form ref="permCollectForm"></perm-collect-form>
|
<perm-collect-form ref="permCollectForm"></perm-collect-form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import userForm from './module/userForm'
|
import userForm from './module/userForm'
|
||||||
import PermCollectForm from './module/permCollectForm'
|
import PermCollectForm from './module/permCollectForm'
|
||||||
import { deleteUserById, searchUser, getOnDutyUser } from '@/modules/acl/api/user'
|
import { deleteUserById, searchUser, getOnDutyUser } from '@/modules/acl/api/user'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Users',
|
name: 'Users',
|
||||||
components: {
|
components: {
|
||||||
userForm,
|
userForm,
|
||||||
PermCollectForm,
|
PermCollectForm,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
tableColumns: [
|
tableColumns: [
|
||||||
{
|
{
|
||||||
title: '用户名',
|
title: '用户名',
|
||||||
field: 'username',
|
field: 'username',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
minWidth: '100px',
|
minWidth: '100px',
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '中文名',
|
title: '中文名',
|
||||||
field: 'nickname',
|
field: 'nickname',
|
||||||
minWidth: '100px',
|
minWidth: '100px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '加入时间',
|
title: '加入时间',
|
||||||
field: 'date_joined',
|
field: 'date_joined',
|
||||||
minWidth: '160px',
|
minWidth: '160px',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '锁定',
|
title: '锁定',
|
||||||
field: 'block',
|
field: 'block',
|
||||||
width: '150px',
|
width: '150px',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
slots: {
|
slots: {
|
||||||
default: 'block_default',
|
default: 'block_default',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
field: 'action',
|
field: 'action',
|
||||||
width: '150px',
|
width: '150px',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
slots: {
|
slots: {
|
||||||
default: 'action_default',
|
default: 'action_default',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
onDutuUids: [],
|
onDutuUids: [],
|
||||||
btnName: '新增用户',
|
btnName: '新增用户',
|
||||||
allUsers: [],
|
allUsers: [],
|
||||||
tableData: [],
|
tableData: [],
|
||||||
searchName: '',
|
searchName: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
this.form = this.$form.createForm(this)
|
this.form = this.$form.createForm(this)
|
||||||
},
|
},
|
||||||
async beforeMount() {
|
async beforeMount() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
await getOnDutyUser().then((res) => {
|
await this.getOnDutyUser()
|
||||||
this.onDutuUids = res.map((i) => i.uid)
|
this.search()
|
||||||
this.search()
|
},
|
||||||
})
|
computed: {
|
||||||
},
|
...mapState({
|
||||||
computed: {
|
windowHeight: (state) => state.windowHeight,
|
||||||
...mapState({
|
}),
|
||||||
windowHeight: (state) => state.windowHeight,
|
isAclAdmin: function() {
|
||||||
}),
|
if (this.$store.state.user.roles.permissions.filter((item) => item === 'acl_admin').length > 0) {
|
||||||
isAclAdmin: function() {
|
return true
|
||||||
if (this.$store.state.user.roles.permissions.filter((item) => item === 'acl_admin').length > 0) {
|
} else {
|
||||||
return true
|
return false
|
||||||
} else {
|
}
|
||||||
return false
|
},
|
||||||
}
|
},
|
||||||
},
|
watch: {
|
||||||
},
|
searchName: {
|
||||||
watch: {
|
immediate: true,
|
||||||
searchName: {
|
handler(newVal, oldVal) {
|
||||||
immediate: true,
|
if (newVal) {
|
||||||
handler(newVal, oldVal) {
|
this.tableData = this.allUsers.filter(
|
||||||
if (newVal) {
|
(item) =>
|
||||||
this.tableData = this.allUsers.filter(
|
item.username.toLowerCase().includes(newVal.toLowerCase()) ||
|
||||||
(item) =>
|
item.nickname.toLowerCase().includes(newVal.toLowerCase())
|
||||||
item.username.toLowerCase().includes(newVal.toLowerCase()) ||
|
)
|
||||||
item.nickname.toLowerCase().includes(newVal.toLowerCase())
|
} else {
|
||||||
)
|
this.tableData = this.allUsers
|
||||||
} else {
|
}
|
||||||
this.tableData = this.allUsers
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
mounted() {},
|
||||||
},
|
inject: ['reload'],
|
||||||
mounted() {},
|
|
||||||
inject: ['reload'],
|
methods: {
|
||||||
|
async getOnDutyUser() {
|
||||||
methods: {
|
await getOnDutyUser().then((res) => {
|
||||||
search() {
|
this.onDutuUids = res.map((i) => i.uid)
|
||||||
searchUser({ page_size: 10000 }).then((res) => {
|
})
|
||||||
const ret = res.users.filter((u) => this.onDutuUids.includes(u.uid))
|
},
|
||||||
this.allUsers = ret
|
search() {
|
||||||
this.tableData = ret
|
searchUser({ page_size: 10000 }).then((res) => {
|
||||||
this.loading = false
|
const ret = res.users.filter((u) => this.onDutuUids.includes(u.uid))
|
||||||
})
|
this.allUsers = ret
|
||||||
},
|
this.tableData = ret
|
||||||
handlePermCollect(record) {
|
this.loading = false
|
||||||
this.$refs['permCollectForm'].collect(record)
|
})
|
||||||
},
|
},
|
||||||
handleEdit(record) {
|
handlePermCollect(record) {
|
||||||
this.$refs.userForm.handleEdit(record)
|
this.$refs['permCollectForm'].collect(record)
|
||||||
},
|
},
|
||||||
handleOk() {
|
handleEdit(record) {
|
||||||
this.searchName = ''
|
this.$refs.userForm.handleEdit(record)
|
||||||
this.search()
|
},
|
||||||
},
|
async handleOk() {
|
||||||
handleCreate() {
|
this.searchName = ''
|
||||||
this.$refs.userForm.handleCreate()
|
await this.getOnDutyUser()
|
||||||
},
|
this.search()
|
||||||
deleteUser(uid) {
|
},
|
||||||
deleteUserById(uid).then((res) => {
|
handleCreate() {
|
||||||
this.$message.success(`删除成功!`)
|
this.$refs.userForm.handleCreate()
|
||||||
this.handleOk()
|
},
|
||||||
})
|
deleteUser(uid) {
|
||||||
},
|
deleteUserById(uid).then((res) => {
|
||||||
},
|
this.$message.success(`删除成功!`)
|
||||||
}
|
this.handleOk()
|
||||||
</script>
|
})
|
||||||
|
},
|
||||||
<style lang="less" scoped>
|
},
|
||||||
.acl-users {
|
}
|
||||||
border-radius: 15px;
|
</script>
|
||||||
background-color: #fff;
|
|
||||||
height: calc(100vh - 64px);
|
<style lang="less" scoped>
|
||||||
margin-bottom: -24px;
|
.acl-users {
|
||||||
padding: 24px;
|
border-radius: 15px;
|
||||||
.acl-users-header {
|
background-color: #fff;
|
||||||
display: inline-flex;
|
height: calc(100vh - 64px);
|
||||||
margin-bottom: 15px;
|
margin-bottom: -24px;
|
||||||
}
|
padding: 24px;
|
||||||
}
|
.acl-users-header {
|
||||||
</style>
|
display: inline-flex;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -940,10 +940,10 @@ export default {
|
||||||
),
|
),
|
||||||
onOk() {
|
onOk() {
|
||||||
const _tempTree = that.treeKeys[that.treeKeys.length - 1].split('%')
|
const _tempTree = that.treeKeys[that.treeKeys.length - 1].split('%')
|
||||||
const firstCIObj = JSON.parse(_tempTree[2])
|
const first_ci_id = Number(_tempTree[0])
|
||||||
batchDeleteCIRelation(
|
batchDeleteCIRelation(
|
||||||
that.selectedRowKeys.map((item) => item._id),
|
that.selectedRowKeys.map((item) => item._id),
|
||||||
firstCIObj
|
[first_ci_id]
|
||||||
).then((res) => {
|
).then((res) => {
|
||||||
that.$refs.xTable.clearCheckboxRow()
|
that.$refs.xTable.clearCheckboxRow()
|
||||||
that.$refs.xTable.clearCheckboxReserve()
|
that.$refs.xTable.clearCheckboxReserve()
|
||||||
|
|
Loading…
Reference in New Issue