mirror of
https://github.com/veops/cmdb.git
synced 2025-08-07 13:48:06 +08:00
feat: dynamic attribute (#534)
This commit is contained in:
@@ -383,12 +383,12 @@ class CIManager(object):
|
||||
computed_attrs.append(attr.to_dict())
|
||||
elif attr.is_password:
|
||||
if attr.name in ci_dict:
|
||||
password_dict[attr.id] = ci_dict.pop(attr.name)
|
||||
password_dict[attr.id] = (ci_dict.pop(attr.name), attr.is_dynamic)
|
||||
elif attr.alias in ci_dict:
|
||||
password_dict[attr.id] = ci_dict.pop(attr.alias)
|
||||
password_dict[attr.id] = (ci_dict.pop(attr.alias), attr.is_dynamic)
|
||||
|
||||
if attr.re_check and password_dict.get(attr.id):
|
||||
value_manager.check_re(attr.re_check, password_dict[attr.id])
|
||||
value_manager.check_re(attr.re_check, password_dict[attr.id][0])
|
||||
|
||||
if computed_attrs:
|
||||
value_manager.handle_ci_compute_attributes(ci_dict, computed_attrs, ci)
|
||||
@@ -421,7 +421,8 @@ class CIManager(object):
|
||||
operate_type = OperateType.UPDATE if ci is not None else OperateType.ADD
|
||||
try:
|
||||
ci = ci or CI.create(type_id=ci_type.id, is_auto_discovery=is_auto_discovery)
|
||||
record_id = value_manager.create_or_update_attr_value(ci, ci_dict, key2attr, ticket_id=ticket_id)
|
||||
record_id, has_dynamic = value_manager.create_or_update_attr_value(
|
||||
ci, ci_dict, key2attr, ticket_id=ticket_id)
|
||||
except BadRequest as e:
|
||||
if existed is None:
|
||||
cls.delete(ci.id)
|
||||
@@ -431,7 +432,7 @@ class CIManager(object):
|
||||
for attr_id in password_dict:
|
||||
record_id = cls.save_password(ci.id, attr_id, password_dict[attr_id], record_id, ci_type.id)
|
||||
|
||||
if record_id: # has change
|
||||
if record_id or has_dynamic: # has change
|
||||
ci_cache.apply_async(args=(ci.id, operate_type, record_id), queue=CMDB_QUEUE)
|
||||
|
||||
if ref_ci_dict: # add relations
|
||||
@@ -440,7 +441,6 @@ class CIManager(object):
|
||||
return ci.id
|
||||
|
||||
def update(self, ci_id, _is_admin=False, ticket_id=None, __sync=False, **ci_dict):
|
||||
current_app.logger.info((ci_id, ci_dict, __sync))
|
||||
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
ci = self.confirm_ci_existed(ci_id)
|
||||
|
||||
@@ -465,12 +465,12 @@ class CIManager(object):
|
||||
computed_attrs.append(attr.to_dict())
|
||||
elif attr.is_password:
|
||||
if attr.name in ci_dict:
|
||||
password_dict[attr.id] = ci_dict.pop(attr.name)
|
||||
password_dict[attr.id] = (ci_dict.pop(attr.name), attr.is_dynamic)
|
||||
elif attr.alias in ci_dict:
|
||||
password_dict[attr.id] = ci_dict.pop(attr.alias)
|
||||
password_dict[attr.id] = (ci_dict.pop(attr.alias), attr.is_dynamic)
|
||||
|
||||
if attr.re_check and password_dict.get(attr.id):
|
||||
value_manager.check_re(attr.re_check, password_dict[attr.id])
|
||||
value_manager.check_re(attr.re_check, password_dict[attr.id][0])
|
||||
|
||||
if computed_attrs:
|
||||
value_manager.handle_ci_compute_attributes(ci_dict, computed_attrs, ci)
|
||||
@@ -495,7 +495,8 @@ class CIManager(object):
|
||||
ci_dict.pop(k)
|
||||
|
||||
try:
|
||||
record_id = value_manager.create_or_update_attr_value(ci, ci_dict, key2attr, ticket_id=ticket_id)
|
||||
record_id, has_dynamic = value_manager.create_or_update_attr_value(
|
||||
ci, ci_dict, key2attr, ticket_id=ticket_id)
|
||||
except BadRequest as e:
|
||||
raise e
|
||||
|
||||
@@ -503,25 +504,25 @@ class CIManager(object):
|
||||
for attr_id in password_dict:
|
||||
record_id = self.save_password(ci.id, attr_id, password_dict[attr_id], record_id, ci.type_id)
|
||||
|
||||
if record_id: # has change
|
||||
if record_id or has_dynamic: # has change
|
||||
if not __sync:
|
||||
ci_cache.apply_async(args=(ci_id, OperateType.UPDATE, record_id), queue=CMDB_QUEUE)
|
||||
else:
|
||||
ci_cache((ci_id, OperateType.UPDATE, record_id))
|
||||
ci_cache(ci_id, OperateType.UPDATE, record_id)
|
||||
|
||||
ref_ci_dict = {k: v for k, v in ci_dict.items() if k.startswith("$") and "." in k}
|
||||
if ref_ci_dict:
|
||||
if not __sync:
|
||||
ci_relation_add.apply_async(args=(ref_ci_dict, ci.id), queue=CMDB_QUEUE)
|
||||
else:
|
||||
ci_relation_add((ref_ci_dict, ci.id))
|
||||
ci_relation_add(ref_ci_dict, ci.id)
|
||||
|
||||
@staticmethod
|
||||
def update_unique_value(ci_id, unique_name, unique_value):
|
||||
ci = CI.get_by_id(ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id)))
|
||||
|
||||
key2attr = {unique_name: AttributeCache.get(unique_name)}
|
||||
record_id = AttributeValueManager().create_or_update_attr_value(ci, {unique_name: unique_value}, key2attr)
|
||||
record_id, _ = AttributeValueManager().create_or_update_attr_value(ci, {unique_name: unique_value}, key2attr)
|
||||
|
||||
ci_cache.apply_async(args=(ci_id, OperateType.UPDATE, record_id), queue=CMDB_QUEUE)
|
||||
|
||||
@@ -761,6 +762,7 @@ class CIManager(object):
|
||||
|
||||
@classmethod
|
||||
def save_password(cls, ci_id, attr_id, value, record_id, type_id):
|
||||
value, is_dynamic = value
|
||||
changed = None
|
||||
encrypt_value = None
|
||||
value_table = ValueTypeMap.table[ValueTypeEnum.PASSWORD]
|
||||
@@ -777,14 +779,18 @@ class CIManager(object):
|
||||
if existed is None:
|
||||
if value:
|
||||
value_table.create(ci_id=ci_id, attr_id=attr_id, value=encrypt_value)
|
||||
changed = [(ci_id, attr_id, OperateType.ADD, '', PASSWORD_DEFAULT_SHOW, type_id)]
|
||||
if not is_dynamic:
|
||||
changed = [(ci_id, attr_id, OperateType.ADD, '', PASSWORD_DEFAULT_SHOW, type_id)]
|
||||
elif existed.value != encrypt_value:
|
||||
if value:
|
||||
existed.update(ci_id=ci_id, attr_id=attr_id, value=encrypt_value)
|
||||
changed = [(ci_id, attr_id, OperateType.UPDATE, PASSWORD_DEFAULT_SHOW, PASSWORD_DEFAULT_SHOW, type_id)]
|
||||
if not is_dynamic:
|
||||
changed = [(ci_id, attr_id, OperateType.UPDATE, PASSWORD_DEFAULT_SHOW,
|
||||
PASSWORD_DEFAULT_SHOW, type_id)]
|
||||
else:
|
||||
existed.delete()
|
||||
changed = [(ci_id, attr_id, OperateType.DELETE, PASSWORD_DEFAULT_SHOW, '', type_id)]
|
||||
if not is_dynamic:
|
||||
changed = [(ci_id, attr_id, OperateType.DELETE, PASSWORD_DEFAULT_SHOW, '', type_id)]
|
||||
|
||||
if current_app.config.get('SECRETS_ENGINE') == 'vault':
|
||||
vault = VaultClient(current_app.config.get('VAULT_URL'), current_app.config.get('VAULT_TOKEN'))
|
||||
|
@@ -856,7 +856,9 @@ class CITypeRelationManager(object):
|
||||
if ci_type is None:
|
||||
return nodes, edges
|
||||
|
||||
nodes.append(ci_type.to_dict())
|
||||
ci_type_dict = ci_type.to_dict()
|
||||
ci_type_dict.setdefault('level', [0])
|
||||
nodes.append(ci_type_dict)
|
||||
node_ids.add(ci_type.id)
|
||||
|
||||
def _find(_id, lv):
|
||||
|
@@ -172,6 +172,7 @@ class TopologyViewManager(object):
|
||||
_type = CITypeCache.get(central_node_type)
|
||||
if not _type:
|
||||
return dict(nodes=nodes, links=links)
|
||||
type2meta = {_type.id: _type.icon}
|
||||
root_ids = []
|
||||
show_key = AttributeCache.get(_type.show_id or _type.unique_id)
|
||||
|
||||
@@ -192,7 +193,6 @@ class TopologyViewManager(object):
|
||||
prefix = REDIS_PREFIX_CI_RELATION
|
||||
key = list(map(str, root_ids))
|
||||
id2node = {}
|
||||
type2meta = {}
|
||||
for level in sorted([i for i in path.keys() if int(i) > 0]):
|
||||
type_ids = {int(i) for i in path[level]}
|
||||
|
||||
|
@@ -253,6 +253,9 @@ def is_app_admin(app=None):
|
||||
if app is None:
|
||||
return False
|
||||
|
||||
if hasattr(current_user, 'username') and current_user.username == 'worker':
|
||||
return True
|
||||
|
||||
app_id = app.id
|
||||
if 'acl_admin' in session.get("acl", {}).get("parentRoles", []):
|
||||
return True
|
||||
|
@@ -79,7 +79,8 @@ class PermissionCRUD(object):
|
||||
return r and cls.get_all(r.id)
|
||||
|
||||
@staticmethod
|
||||
def grant(rid, perms, resource_id=None, group_id=None, rebuild=True, source=AuditOperateSource.acl):
|
||||
def grant(rid, perms, resource_id=None, group_id=None, rebuild=True,
|
||||
source=AuditOperateSource.acl, force_update=False):
|
||||
app_id = None
|
||||
rt_id = None
|
||||
|
||||
@@ -106,8 +107,23 @@ class PermissionCRUD(object):
|
||||
if not perms:
|
||||
perms = [i.get('name') for i in ResourceTypeCRUD.get_perms(group.resource_type_id)]
|
||||
|
||||
_role_permissions = []
|
||||
if force_update:
|
||||
revoke_role_permissions = []
|
||||
existed_perms = RolePermission.get_by(rid=rid,
|
||||
app_id=app_id,
|
||||
group_id=group_id,
|
||||
resource_id=resource_id,
|
||||
to_dict=False)
|
||||
for role_perm in existed_perms:
|
||||
perm = PermissionCache.get(role_perm.perm_id, rt_id)
|
||||
if perm and perm.name not in perms:
|
||||
role_perm.soft_delete()
|
||||
revoke_role_permissions.append(role_perm)
|
||||
|
||||
AuditCRUD.add_permission_log(app_id, AuditOperateType.revoke, rid, rt_id,
|
||||
revoke_role_permissions, source=source)
|
||||
|
||||
_role_permissions = []
|
||||
for _perm in set(perms):
|
||||
perm = PermissionCache.get(_perm, rt_id)
|
||||
if not perm:
|
||||
|
@@ -51,12 +51,12 @@ def _auth_with_key():
|
||||
user, authenticated = User.query.authenticate_with_key(key, secret, req_args, path)
|
||||
if user and authenticated:
|
||||
login_user(user)
|
||||
reset_session(user)
|
||||
# reset_session(user)
|
||||
return True
|
||||
|
||||
role, authenticated = Role.query.authenticate_with_key(key, secret, req_args, path)
|
||||
if role and authenticated:
|
||||
reset_session(None, role=role.name)
|
||||
# reset_session(None, role=role.name)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
@@ -104,6 +104,7 @@ class Attribute(Model):
|
||||
is_link = db.Column(db.Boolean, default=False)
|
||||
is_password = db.Column(db.Boolean, default=False)
|
||||
is_sortable = db.Column(db.Boolean, default=False)
|
||||
is_dynamic = db.Column(db.Boolean, default=False)
|
||||
|
||||
default = db.Column(db.JSON) # {"default": None}
|
||||
|
||||
|
Reference in New Issue
Block a user