mirror of https://github.com/veops/cmdb.git
Merge branch 'master' of github.com:veops/cmdb into dev_ui
This commit is contained in:
commit
7110b4bcb3
|
@ -22,13 +22,24 @@ class InitEmployee(object):
|
||||||
Import users from ACL
|
Import users from ACL
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
InitDepartment().init()
|
||||||
acl = ACLManager('acl')
|
acl = ACLManager('acl')
|
||||||
user_list = acl.get_all_users()
|
user_list = acl.get_all_users()
|
||||||
|
|
||||||
username_list = [e['username'] for e in Employee.get_by()]
|
username_list = [e['username'] for e in Employee.get_by()]
|
||||||
|
|
||||||
for user in user_list:
|
for user in user_list:
|
||||||
|
acl_uid = user['uid']
|
||||||
|
block = 1 if user['block'] else 0
|
||||||
|
acl_rid = self.get_rid_by_uid(acl_uid)
|
||||||
if user['username'] in username_list:
|
if user['username'] in username_list:
|
||||||
|
existed = Employee.get_by(first=True, username=user['username'], to_dict=False)
|
||||||
|
if existed:
|
||||||
|
existed.update(
|
||||||
|
acl_uid=acl_uid,
|
||||||
|
acl_rid=acl_rid,
|
||||||
|
block=block,
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
form = EmployeeAddForm(MultiDict(user))
|
form = EmployeeAddForm(MultiDict(user))
|
||||||
|
@ -36,8 +47,9 @@ class InitEmployee(object):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
','.join(['{}: {}'.format(filed, ','.join(msg)) for filed, msg in form.errors.items()]))
|
','.join(['{}: {}'.format(filed, ','.join(msg)) for filed, msg in form.errors.items()]))
|
||||||
data = form.data
|
data = form.data
|
||||||
data['acl_uid'] = user['uid']
|
data['acl_uid'] = acl_uid
|
||||||
data['block'] = 1 if user['block'] else 0
|
data['acl_rid'] = acl_rid
|
||||||
|
data['block'] = block
|
||||||
data.pop('password')
|
data.pop('password')
|
||||||
Employee.create(
|
Employee.create(
|
||||||
**data
|
**data
|
||||||
|
@ -46,6 +58,11 @@ class InitEmployee(object):
|
||||||
self.log.error(ErrFormat.acl_import_user_failed.format(user['username'], str(e)))
|
self.log.error(ErrFormat.acl_import_user_failed.format(user['username'], str(e)))
|
||||||
self.log.error(e)
|
self.log.error(e)
|
||||||
|
|
||||||
|
def get_rid_by_uid(self, uid):
|
||||||
|
from api.models.acl import Role
|
||||||
|
role = Role.get_by(first=True, uid=uid)
|
||||||
|
return role['id'] if role is not None else 0
|
||||||
|
|
||||||
|
|
||||||
class InitDepartment(object):
|
class InitDepartment(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
@ -8,6 +8,7 @@ from flask_login import current_user
|
||||||
|
|
||||||
from api.extensions import db
|
from api.extensions import db
|
||||||
from api.lib.cmdb.cache import AttributeCache
|
from api.lib.cmdb.cache import AttributeCache
|
||||||
|
from api.lib.cmdb.cache import CITypeCache
|
||||||
from api.lib.cmdb.const import CITypeOperateType
|
from api.lib.cmdb.const import CITypeOperateType
|
||||||
from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum
|
from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum
|
||||||
from api.lib.cmdb.const import ValueTypeEnum
|
from api.lib.cmdb.const import ValueTypeEnum
|
||||||
|
@ -319,7 +320,12 @@ class AttributeManager(object):
|
||||||
if CIType.get_by(unique_id=attr.id, first=True, to_dict=False) is not None:
|
if CIType.get_by(unique_id=attr.id, first=True, to_dict=False) is not None:
|
||||||
return abort(400, ErrFormat.attribute_is_unique_id)
|
return abort(400, ErrFormat.attribute_is_unique_id)
|
||||||
|
|
||||||
if attr.uid and attr.uid != current_user.uid:
|
ref = CITypeAttribute.get_by(attr_id=_id, to_dict=False, first=True)
|
||||||
|
if ref is not None:
|
||||||
|
ci_type = CITypeCache.get(ref.type_id)
|
||||||
|
return abort(400, ErrFormat.attribute_is_ref_by_type.format(ci_type.alias))
|
||||||
|
|
||||||
|
if attr.uid != current_user.uid and not is_app_admin('cmdb'):
|
||||||
return abort(403, ErrFormat.cannot_delete_attribute)
|
return abort(403, ErrFormat.cannot_delete_attribute)
|
||||||
|
|
||||||
if attr.is_choice:
|
if attr.is_choice:
|
||||||
|
@ -331,9 +337,6 @@ class AttributeManager(object):
|
||||||
|
|
||||||
attr.soft_delete()
|
attr.soft_delete()
|
||||||
|
|
||||||
for i in CITypeAttribute.get_by(attr_id=_id, to_dict=False):
|
|
||||||
i.soft_delete()
|
|
||||||
|
|
||||||
for i in PreferenceShowAttributes.get_by(attr_id=_id, to_dict=False):
|
for i in PreferenceShowAttributes.get_by(attr_id=_id, to_dict=False):
|
||||||
i.soft_delete()
|
i.soft_delete()
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ from api.lib.decorator import kwargs_required
|
||||||
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.perm.acl.acl import validate_permission
|
from api.lib.perm.acl.acl import validate_permission
|
||||||
from api.lib.utils import handle_arg_list
|
|
||||||
from api.lib.utils import Lock
|
from api.lib.utils import Lock
|
||||||
|
from api.lib.utils import handle_arg_list
|
||||||
from api.models.cmdb import CI
|
from api.models.cmdb import CI
|
||||||
from api.models.cmdb import CIRelation
|
from api.models.cmdb import CIRelation
|
||||||
from api.models.cmdb import CITypeAttribute
|
from api.models.cmdb import CITypeAttribute
|
||||||
|
@ -49,6 +49,8 @@ from api.tasks.cmdb import ci_delete
|
||||||
from api.tasks.cmdb import ci_relation_cache
|
from api.tasks.cmdb import ci_relation_cache
|
||||||
from api.tasks.cmdb import ci_relation_delete
|
from api.tasks.cmdb import ci_relation_delete
|
||||||
|
|
||||||
|
PRIVILEGED_USERS = {"worker", "cmdb_agent", "agent"}
|
||||||
|
|
||||||
|
|
||||||
class CIManager(object):
|
class CIManager(object):
|
||||||
""" manage CI interface
|
""" manage CI interface
|
||||||
|
@ -316,7 +318,7 @@ class CIManager(object):
|
||||||
ci_attr2type_attr = {type_attr.attr_id: type_attr for type_attr, _ in attrs}
|
ci_attr2type_attr = {type_attr.attr_id: type_attr for type_attr, _ in attrs}
|
||||||
|
|
||||||
ci = None
|
ci = None
|
||||||
need_lock = current_user.username not in ("worker", "cmdb_agent", "agent")
|
need_lock = current_user.username not in current_app.config.get('PRIVILEGED_USERS', PRIVILEGED_USERS)
|
||||||
with Lock(ci_type_name, need_lock=need_lock):
|
with Lock(ci_type_name, need_lock=need_lock):
|
||||||
existed = cls.ci_is_exist(unique_key, unique_value, ci_type.id)
|
existed = cls.ci_is_exist(unique_key, unique_value, ci_type.id)
|
||||||
if existed is not None:
|
if existed is not None:
|
||||||
|
@ -411,7 +413,7 @@ class CIManager(object):
|
||||||
|
|
||||||
limit_attrs = self._valid_ci_for_no_read(ci) if not _is_admin else {}
|
limit_attrs = self._valid_ci_for_no_read(ci) if not _is_admin else {}
|
||||||
|
|
||||||
need_lock = current_user.username not in ("worker", "cmdb_agent", "agent")
|
need_lock = current_user.username not in current_app.config.get('PRIVILEGED_USERS', PRIVILEGED_USERS)
|
||||||
with Lock(ci.ci_type.name, need_lock=need_lock):
|
with Lock(ci.ci_type.name, need_lock=need_lock):
|
||||||
self._valid_unique_constraint(ci.type_id, ci_dict, ci_id)
|
self._valid_unique_constraint(ci.type_id, ci_dict, ci_id)
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ class ErrFormat(CommonErrFormat):
|
||||||
|
|
||||||
attribute_not_found = "属性 {} 不存在!"
|
attribute_not_found = "属性 {} 不存在!"
|
||||||
attribute_is_unique_id = "该属性是模型的唯一标识,不能被删除!"
|
attribute_is_unique_id = "该属性是模型的唯一标识,不能被删除!"
|
||||||
|
attribute_is_ref_by_type = "该属性被模型 {} 引用, 不能删除!"
|
||||||
attribute_value_type_cannot_change = "属性的值类型不允许修改!"
|
attribute_value_type_cannot_change = "属性的值类型不允许修改!"
|
||||||
attribute_list_value_cannot_change = "多值不被允许修改!"
|
attribute_list_value_cannot_change = "多值不被允许修改!"
|
||||||
attribute_index_cannot_change = "修改索引 非管理员不被允许!"
|
attribute_index_cannot_change = "修改索引 非管理员不被允许!"
|
||||||
|
@ -20,7 +21,7 @@ class ErrFormat(CommonErrFormat):
|
||||||
add_attribute_failed = "创建属性 {} 失败!"
|
add_attribute_failed = "创建属性 {} 失败!"
|
||||||
update_attribute_failed = "修改属性 {} 失败!"
|
update_attribute_failed = "修改属性 {} 失败!"
|
||||||
cannot_edit_attribute = "您没有权限修改该属性!"
|
cannot_edit_attribute = "您没有权限修改该属性!"
|
||||||
cannot_delete_attribute = "您没有权限删除该属性!"
|
cannot_delete_attribute = "目前只允许 属性创建人、管理员 删除属性!"
|
||||||
attribute_name_cannot_be_builtin = "属性字段名不能是内置字段: id, _id, ci_id, type, _type, ci_type"
|
attribute_name_cannot_be_builtin = "属性字段名不能是内置字段: id, _id, ci_id, type, _type, ci_type"
|
||||||
|
|
||||||
ci_not_found = "CI {} 不存在"
|
ci_not_found = "CI {} 不存在"
|
||||||
|
|
|
@ -80,10 +80,10 @@ class CRUDMixin(FormatMixin):
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
raise CommitException(str(e))
|
raise CommitException(str(e))
|
||||||
|
|
||||||
def soft_delete(self, flush=False):
|
def soft_delete(self, flush=False, commit=True):
|
||||||
setattr(self, "deleted", True)
|
setattr(self, "deleted", True)
|
||||||
setattr(self, "deleted_at", datetime.datetime.now())
|
setattr(self, "deleted_at", datetime.datetime.now())
|
||||||
self.save(flush=flush)
|
self.save(flush=flush, commit=commit)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_by_id(cls, _id):
|
def get_by_id(cls, _id):
|
||||||
|
@ -138,8 +138,11 @@ class CRUDMixin(FormatMixin):
|
||||||
return result[0] if first and result else (None if first else result)
|
return result[0] if first and result else (None if first else result)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_by_like(cls, to_dict=True, **kwargs):
|
def get_by_like(cls, to_dict=True, deleted=False, **kwargs):
|
||||||
query = db.session.query(cls)
|
query = db.session.query(cls)
|
||||||
|
if hasattr(cls, "deleted") and deleted is not None:
|
||||||
|
query = query.filter(cls.deleted.is_(deleted))
|
||||||
|
|
||||||
for k, v in kwargs.items():
|
for k, v in kwargs.items():
|
||||||
query = query.filter(getattr(cls, k).ilike('%{0}%'.format(v)))
|
query = query.filter(getattr(cls, k).ilike('%{0}%'.format(v)))
|
||||||
return [i.to_dict() if to_dict else i for i in query]
|
return [i.to_dict() if to_dict else i for i in query]
|
||||||
|
|
|
@ -17,6 +17,7 @@ class ErrFormat(CommonErrFormat):
|
||||||
role_exists = "角色 {} 已经存在!"
|
role_exists = "角色 {} 已经存在!"
|
||||||
global_role_not_found = "全局角色 {} 不存在!"
|
global_role_not_found = "全局角色 {} 不存在!"
|
||||||
global_role_exists = "全局角色 {} 已经存在!"
|
global_role_exists = "全局角色 {} 已经存在!"
|
||||||
|
user_role_delete_invalid = "删除用户角色, 请在 用户管理 页面操作!"
|
||||||
|
|
||||||
resource_no_permission = "您没有资源: {} 的 {} 权限"
|
resource_no_permission = "您没有资源: {} 的 {} 权限"
|
||||||
admin_required = "需要管理员权限"
|
admin_required = "需要管理员权限"
|
||||||
|
|
|
@ -285,11 +285,13 @@ class RoleCRUD(object):
|
||||||
return role
|
return role
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete_role(cls, rid):
|
def delete_role(cls, rid, force=False):
|
||||||
from api.lib.perm.acl.acl import is_admin
|
from api.lib.perm.acl.acl import is_admin
|
||||||
|
|
||||||
role = Role.get_by_id(rid) or abort(404, ErrFormat.role_not_found.format("rid={}".format(rid)))
|
role = Role.get_by_id(rid) or abort(404, ErrFormat.role_not_found.format("rid={}".format(rid)))
|
||||||
|
|
||||||
|
not force and role.uid and abort(400, ErrFormat.user_role_delete_invalid)
|
||||||
|
|
||||||
if not role.app_id and not is_admin():
|
if not role.app_id and not is_admin():
|
||||||
return abort(403, ErrFormat.admin_required)
|
return abort(403, ErrFormat.admin_required)
|
||||||
|
|
||||||
|
@ -301,18 +303,20 @@ class RoleCRUD(object):
|
||||||
|
|
||||||
for i in RoleRelation.get_by(parent_id=rid, to_dict=False):
|
for i in RoleRelation.get_by(parent_id=rid, to_dict=False):
|
||||||
child_ids.append(i.child_id)
|
child_ids.append(i.child_id)
|
||||||
i.soft_delete()
|
i.soft_delete(commit=False)
|
||||||
|
|
||||||
for i in RoleRelation.get_by(child_id=rid, to_dict=False):
|
for i in RoleRelation.get_by(child_id=rid, to_dict=False):
|
||||||
parent_ids.append(i.parent_id)
|
parent_ids.append(i.parent_id)
|
||||||
i.soft_delete()
|
i.soft_delete(commit=False)
|
||||||
|
|
||||||
role_permissions = []
|
role_permissions = []
|
||||||
for i in RolePermission.get_by(rid=rid, to_dict=False):
|
for i in RolePermission.get_by(rid=rid, to_dict=False):
|
||||||
role_permissions.append(i.to_dict())
|
role_permissions.append(i.to_dict())
|
||||||
i.soft_delete()
|
i.soft_delete(commit=False)
|
||||||
|
|
||||||
role.soft_delete()
|
role.soft_delete(commit=False)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
role_rebuild.apply_async(args=(recursive_child_ids, role.app_id), queue=ACL_QUEUE)
|
role_rebuild.apply_async(args=(recursive_child_ids, role.app_id), queue=ACL_QUEUE)
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,10 @@ class UserCRUD(object):
|
||||||
|
|
||||||
UserCache.clean(user)
|
UserCache.clean(user)
|
||||||
|
|
||||||
|
role = RoleCRUD.get_by_name(user.username, app_id=None)
|
||||||
|
if role:
|
||||||
|
RoleCRUD.delete_role(role[0]['id'], force=True)
|
||||||
|
|
||||||
AuditCRUD.add_role_log(None, AuditOperateType.delete,
|
AuditCRUD.add_role_log(None, AuditOperateType.delete,
|
||||||
AuditScope.user, user.uid, origin, {}, {}, {})
|
AuditScope.user, user.uid, origin, {}, {}, {})
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ class AttributeView(APIView):
|
||||||
current_app.logger.debug(params)
|
current_app.logger.debug(params)
|
||||||
|
|
||||||
attr_id = AttributeManager.add(**params)
|
attr_id = AttributeManager.add(**params)
|
||||||
|
|
||||||
return self.jsonify(attr_id=attr_id)
|
return self.jsonify(attr_id=attr_id)
|
||||||
|
|
||||||
@args_validate(AttributeManager.cls)
|
@args_validate(AttributeManager.cls)
|
||||||
|
@ -72,8 +73,10 @@ class AttributeView(APIView):
|
||||||
params["choice_value"] = choice_value
|
params["choice_value"] = choice_value
|
||||||
current_app.logger.debug(params)
|
current_app.logger.debug(params)
|
||||||
AttributeManager().update(attr_id, **params)
|
AttributeManager().update(attr_id, **params)
|
||||||
|
|
||||||
return self.jsonify(attr_id=attr_id)
|
return self.jsonify(attr_id=attr_id)
|
||||||
|
|
||||||
def delete(self, attr_id):
|
def delete(self, attr_id):
|
||||||
attr_name = AttributeManager.delete(attr_id)
|
attr_name = AttributeManager.delete(attr_id)
|
||||||
|
|
||||||
return self.jsonify(message="attribute {0} deleted".format(attr_name))
|
return self.jsonify(message="attribute {0} deleted".format(attr_name))
|
||||||
|
|
|
@ -75,9 +75,9 @@ class AutoDiscoveryRuleTemplateFileView(APIView):
|
||||||
|
|
||||||
return self.send_file(bf,
|
return self.send_file(bf,
|
||||||
as_attachment=True,
|
as_attachment=True,
|
||||||
attachment_filename="cmdb_auto_discovery.json",
|
download_name="cmdb_auto_discovery.json",
|
||||||
mimetype='application/json',
|
mimetype='application/json',
|
||||||
cache_timeout=0)
|
max_age=0)
|
||||||
|
|
||||||
def post(self):
|
def post(self):
|
||||||
f = request.files.get('file')
|
f = request.files.get('file')
|
||||||
|
|
|
@ -350,9 +350,9 @@ class CITypeTemplateFileView(APIView):
|
||||||
|
|
||||||
return self.send_file(bf,
|
return self.send_file(bf,
|
||||||
as_attachment=True,
|
as_attachment=True,
|
||||||
attachment_filename="cmdb_template.json",
|
download_name="cmdb_template.json",
|
||||||
mimetype='application/json',
|
mimetype='application/json',
|
||||||
cache_timeout=0)
|
max_age=0)
|
||||||
|
|
||||||
@role_required(RoleEnum.CONFIG)
|
@role_required(RoleEnum.CONFIG)
|
||||||
def post(self): # import
|
def post(self): # import
|
||||||
|
|
Loading…
Reference in New Issue