mirror of
				https://github.com/veops/cmdb.git
				synced 2025-11-04 21:56:16 +08:00 
			
		
		
		
	feat(api): ci baseline rollback (#498)
This commit is contained in:
		@@ -441,10 +441,13 @@ class CIManager(object):
 | 
				
			|||||||
        now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
 | 
					        now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
 | 
				
			||||||
        ci = self.confirm_ci_existed(ci_id)
 | 
					        ci = self.confirm_ci_existed(ci_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        raw_dict = copy.deepcopy(ci_dict)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        attrs = CITypeAttributeManager.get_all_attributes(ci.type_id)
 | 
					        attrs = CITypeAttributeManager.get_all_attributes(ci.type_id)
 | 
				
			||||||
        ci_type_attrs_name = {attr.name: attr for _, attr in attrs}
 | 
					        ci_type_attrs_name = {attr.name: attr for _, attr in attrs}
 | 
				
			||||||
 | 
					        ci_type_attrs_alias2name = {attr.alias: attr.name for _, attr in attrs}
 | 
				
			||||||
 | 
					        ci_dict = {ci_type_attrs_alias2name[k] if k in ci_type_attrs_alias2name else k: v for k, v in ci_dict.items()}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        raw_dict = copy.deepcopy(ci_dict)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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}
 | 
				
			||||||
        for _, attr in attrs:
 | 
					        for _, attr in attrs:
 | 
				
			||||||
            if attr.default and attr.default.get('default') == AttributeDefaultValueEnum.UPDATED_AT:
 | 
					            if attr.default and attr.default.get('default') == AttributeDefaultValueEnum.UPDATED_AT:
 | 
				
			||||||
@@ -825,6 +828,105 @@ class CIManager(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            return data.get('v')
 | 
					            return data.get('v')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def baseline(self, ci_ids, before_date):
 | 
				
			||||||
 | 
					        ci_list = self.get_cis_by_ids(ci_ids, ret_key=RetKey.ALIAS)
 | 
				
			||||||
 | 
					        if not ci_list:
 | 
				
			||||||
 | 
					            return dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ci2changed = dict()
 | 
				
			||||||
 | 
					        changed = AttributeHistoryManger.get_records_for_attributes(
 | 
				
			||||||
 | 
					            before_date, None, None, 1, 100000, None, None, ci_ids=ci_ids, more=True)[1]
 | 
				
			||||||
 | 
					        for records in changed:
 | 
				
			||||||
 | 
					            for change in records[1]:
 | 
				
			||||||
 | 
					                if change['is_computed'] or change['is_password']:
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if change.get('default') and change['default'].get('default') == AttributeDefaultValueEnum.UPDATED_AT:
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ci2changed.setdefault(change['ci_id'], {})
 | 
				
			||||||
 | 
					                item = (change['old'],
 | 
				
			||||||
 | 
					                        change['new'],
 | 
				
			||||||
 | 
					                        change.get('is_list'),
 | 
				
			||||||
 | 
					                        change.get('value_type'),
 | 
				
			||||||
 | 
					                        change['operate_type'])
 | 
				
			||||||
 | 
					                if change.get('is_list'):
 | 
				
			||||||
 | 
					                    ci2changed[change['ci_id']].setdefault(change.get('attr_alias'), []).append(item)
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    ci2changed[change['ci_id']].update({change.get('attr_alias'): item})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        type2show_name = {}
 | 
				
			||||||
 | 
					        result = []
 | 
				
			||||||
 | 
					        for ci in ci_list:
 | 
				
			||||||
 | 
					            list_attr2item = {}
 | 
				
			||||||
 | 
					            for alias_name, v in (ci2changed.get(ci['_id']) or {}).items():
 | 
				
			||||||
 | 
					                if not alias_name:
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                if alias_name == ci.get('unique_alias'):
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if ci.get('_type') not in type2show_name:
 | 
				
			||||||
 | 
					                    ci_type = CITypeCache.get(ci.get('_type'))
 | 
				
			||||||
 | 
					                    show_id = ci_type.show_id or ci_type.unique_id
 | 
				
			||||||
 | 
					                    type2show_name[ci['_type']] = AttributeCache.get(show_id).alias
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if isinstance(v, list):
 | 
				
			||||||
 | 
					                    for old, new, is_list, value_type, operate_type in v:
 | 
				
			||||||
 | 
					                        if alias_name not in list_attr2item:
 | 
				
			||||||
 | 
					                            list_attr2item[alias_name] = dict(instance=ci.get(type2show_name[ci['_type']]),
 | 
				
			||||||
 | 
					                                                              attr_name=alias_name,
 | 
				
			||||||
 | 
					                                                              value_type=value_type,
 | 
				
			||||||
 | 
					                                                              is_list=is_list,
 | 
				
			||||||
 | 
					                                                              ci_type=ci.get('ci_type'),
 | 
				
			||||||
 | 
					                                                              unique_alias=ci.get('unique_alias'),
 | 
				
			||||||
 | 
					                                                              unique_value=ci.get(ci['unique_alias']),
 | 
				
			||||||
 | 
					                                                              cur=copy.deepcopy(ci.get(alias_name)),
 | 
				
			||||||
 | 
					                                                              to=ci.get(alias_name) or [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        old = ValueTypeMap.deserialize[value_type](old) if old else old
 | 
				
			||||||
 | 
					                        new = ValueTypeMap.deserialize[value_type](new) if new else new
 | 
				
			||||||
 | 
					                        if operate_type == OperateType.ADD:
 | 
				
			||||||
 | 
					                            list_attr2item[alias_name]['to'].remove(new)
 | 
				
			||||||
 | 
					                        elif operate_type == OperateType.DELETE and old not in list_attr2item[alias_name]['to']:
 | 
				
			||||||
 | 
					                            list_attr2item[alias_name]['to'].append(old)
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                old, value_type = v[0], v[3]
 | 
				
			||||||
 | 
					                old = ValueTypeMap.deserialize[value_type](old) if old else old
 | 
				
			||||||
 | 
					                if isinstance(old, (datetime.datetime, datetime.date)):
 | 
				
			||||||
 | 
					                    old = str(old)
 | 
				
			||||||
 | 
					                if ci.get(alias_name) != old:
 | 
				
			||||||
 | 
					                    item = dict(instance=ci.get(type2show_name[ci['_type']]),
 | 
				
			||||||
 | 
					                                attr_name=alias_name,
 | 
				
			||||||
 | 
					                                value_type=value_type,
 | 
				
			||||||
 | 
					                                ci_type=ci.get('ci_type'),
 | 
				
			||||||
 | 
					                                unique_alias=ci.get('unique_alias'),
 | 
				
			||||||
 | 
					                                unique_value=ci.get(ci['unique_alias']),
 | 
				
			||||||
 | 
					                                cur=ci.get(alias_name),
 | 
				
			||||||
 | 
					                                to=old)
 | 
				
			||||||
 | 
					                    result.append(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for alias_name, item in list_attr2item.items():
 | 
				
			||||||
 | 
					                if sorted(item['cur'] or []) != sorted(item['to'] or []):
 | 
				
			||||||
 | 
					                    result.append(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def rollback(self, ci_id, before_date):
 | 
				
			||||||
 | 
					        baseline_ci = self.baseline([ci_id], before_date)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        payload = dict()
 | 
				
			||||||
 | 
					        for item in baseline_ci:
 | 
				
			||||||
 | 
					            payload[item.get('attr_name')] = item.get('to')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if payload:
 | 
				
			||||||
 | 
					            payload['ci_type'] = baseline_ci[0]['ci_type']
 | 
				
			||||||
 | 
					            payload[baseline_ci[0]['unique_alias']] = baseline_ci[0]['unique_value']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.update(ci_id, **payload)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return payload
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CIRelationManager(object):
 | 
					class CIRelationManager(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -253,6 +253,13 @@ class CITypeManager(object):
 | 
				
			|||||||
        for item in CITypeInheritance.get_by(child_id=type_id, to_dict=False):
 | 
					        for item in CITypeInheritance.get_by(child_id=type_id, to_dict=False):
 | 
				
			||||||
            item.delete(commit=False)
 | 
					            item.delete(commit=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            from api.models.cmdb import CITypeReconciliation
 | 
				
			||||||
 | 
					            for item in CITypeReconciliation.get_by(type_id=type_id, to_dict=False):
 | 
				
			||||||
 | 
					                item.delete(commit=False)
 | 
				
			||||||
 | 
					        except Exception:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        db.session.commit()
 | 
					        db.session.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ci_type.soft_delete()
 | 
					        ci_type.soft_delete()
 | 
				
			||||||
@@ -414,9 +421,6 @@ class CITypeGroupManager(object):
 | 
				
			|||||||
        existed = CITypeGroup.get_by_id(gid) or abort(
 | 
					        existed = CITypeGroup.get_by_id(gid) or abort(
 | 
				
			||||||
            404, ErrFormat.ci_type_group_not_found.format("id={}".format(gid)))
 | 
					            404, ErrFormat.ci_type_group_not_found.format("id={}".format(gid)))
 | 
				
			||||||
        if name is not None and name != existed.name:
 | 
					        if name is not None and name != existed.name:
 | 
				
			||||||
            if RoleEnum.CONFIG not in session.get("acl", {}).get("parentRoles", []) and not is_app_admin("cmdb"):
 | 
					 | 
				
			||||||
                return abort(403, ErrFormat.role_required.format(RoleEnum.CONFIG))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            existed.update(name=name)
 | 
					            existed.update(name=name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        max_order = max([i.order or 0 for i in CITypeGroupItem.get_by(group_id=gid, to_dict=False)] or [0])
 | 
					        max_order = max([i.order or 0 for i in CITypeGroupItem.get_by(group_id=gid, to_dict=False)] or [0])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,6 +55,9 @@ class CITypeOperateType(BaseEnum):
 | 
				
			|||||||
    DELETE_UNIQUE_CONSTRAINT = "11"  # 删除联合唯一
 | 
					    DELETE_UNIQUE_CONSTRAINT = "11"  # 删除联合唯一
 | 
				
			||||||
    ADD_RELATION = "12"  # 新增关系
 | 
					    ADD_RELATION = "12"  # 新增关系
 | 
				
			||||||
    DELETE_RELATION = "13"  # 删除关系
 | 
					    DELETE_RELATION = "13"  # 删除关系
 | 
				
			||||||
 | 
					    ADD_RECONCILIATION = "14"  # 删除关系
 | 
				
			||||||
 | 
					    UPDATE_RECONCILIATION = "15"  # 删除关系
 | 
				
			||||||
 | 
					    DELETE_RECONCILIATION = "16"  # 删除关系
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RetKey(BaseEnum):
 | 
					class RetKey(BaseEnum):
 | 
				
			||||||
@@ -98,6 +101,12 @@ class AttributeDefaultValueEnum(BaseEnum):
 | 
				
			|||||||
    AUTO_INC_ID = "$auto_inc_id"
 | 
					    AUTO_INC_ID = "$auto_inc_id"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ExecuteStatusEnum(BaseEnum):
 | 
				
			||||||
 | 
					    COMPLETED = '0'
 | 
				
			||||||
 | 
					    FAILED = '1'
 | 
				
			||||||
 | 
					    RUNNING = '2'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CMDB_QUEUE = "one_cmdb_async"
 | 
					CMDB_QUEUE = "one_cmdb_async"
 | 
				
			||||||
REDIS_PREFIX_CI = "ONE_CMDB"
 | 
					REDIS_PREFIX_CI = "ONE_CMDB"
 | 
				
			||||||
REDIS_PREFIX_CI_RELATION = "CMDB_CI_RELATION"
 | 
					REDIS_PREFIX_CI_RELATION = "CMDB_CI_RELATION"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ from api.models.cmdb import OperationRecord
 | 
				
			|||||||
class AttributeHistoryManger(object):
 | 
					class AttributeHistoryManger(object):
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def get_records_for_attributes(start, end, username, page, page_size, operate_type, type_id,
 | 
					    def get_records_for_attributes(start, end, username, page, page_size, operate_type, type_id,
 | 
				
			||||||
                                   ci_id=None, attr_id=None):
 | 
					                                   ci_id=None, attr_id=None, ci_ids=None, more=False):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        records = db.session.query(OperationRecord, AttributeHistory).join(
 | 
					        records = db.session.query(OperationRecord, AttributeHistory).join(
 | 
				
			||||||
            AttributeHistory, OperationRecord.id == AttributeHistory.record_id)
 | 
					            AttributeHistory, OperationRecord.id == AttributeHistory.record_id)
 | 
				
			||||||
@@ -48,6 +48,9 @@ class AttributeHistoryManger(object):
 | 
				
			|||||||
        if ci_id is not None:
 | 
					        if ci_id is not None:
 | 
				
			||||||
            records = records.filter(AttributeHistory.ci_id == ci_id)
 | 
					            records = records.filter(AttributeHistory.ci_id == ci_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ci_ids and isinstance(ci_ids, list):
 | 
				
			||||||
 | 
					            records = records.filter(AttributeHistory.ci_id.in_(ci_ids))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if attr_id is not None:
 | 
					        if attr_id is not None:
 | 
				
			||||||
            records = records.filter(AttributeHistory.attr_id == attr_id)
 | 
					            records = records.filter(AttributeHistory.attr_id == attr_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -62,6 +65,12 @@ class AttributeHistoryManger(object):
 | 
				
			|||||||
            if attr_hist['attr']:
 | 
					            if attr_hist['attr']:
 | 
				
			||||||
                attr_hist['attr_name'] = attr_hist['attr'].name
 | 
					                attr_hist['attr_name'] = attr_hist['attr'].name
 | 
				
			||||||
                attr_hist['attr_alias'] = attr_hist['attr'].alias
 | 
					                attr_hist['attr_alias'] = attr_hist['attr'].alias
 | 
				
			||||||
 | 
					                if more:
 | 
				
			||||||
 | 
					                    attr_hist['is_list'] = attr_hist['attr'].is_list
 | 
				
			||||||
 | 
					                    attr_hist['is_computed'] = attr_hist['attr'].is_computed
 | 
				
			||||||
 | 
					                    attr_hist['is_password'] = attr_hist['attr'].is_password
 | 
				
			||||||
 | 
					                    attr_hist['default'] = attr_hist['attr'].default
 | 
				
			||||||
 | 
					                attr_hist['value_type'] = attr_hist['attr'].value_type
 | 
				
			||||||
                attr_hist.pop("attr")
 | 
					                attr_hist.pop("attr")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if record_id not in res:
 | 
					            if record_id not in res:
 | 
				
			||||||
@@ -161,6 +170,7 @@ class AttributeHistoryManger(object):
 | 
				
			|||||||
            record = i.OperationRecord
 | 
					            record = i.OperationRecord
 | 
				
			||||||
            item = dict(attr_name=attr.name,
 | 
					            item = dict(attr_name=attr.name,
 | 
				
			||||||
                        attr_alias=attr.alias,
 | 
					                        attr_alias=attr.alias,
 | 
				
			||||||
 | 
					                        value_type=attr.value_type,
 | 
				
			||||||
                        operate_type=hist.operate_type,
 | 
					                        operate_type=hist.operate_type,
 | 
				
			||||||
                        username=user and user.nickname,
 | 
					                        username=user and user.nickname,
 | 
				
			||||||
                        old=hist.old,
 | 
					                        old=hist.old,
 | 
				
			||||||
@@ -271,7 +281,7 @@ class CITypeHistoryManager(object):
 | 
				
			|||||||
        return numfound, result
 | 
					        return numfound, result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def add(operate_type, type_id, attr_id=None, trigger_id=None, unique_constraint_id=None, change=None):
 | 
					    def add(operate_type, type_id, attr_id=None, trigger_id=None, unique_constraint_id=None, change=None, rc_id=None):
 | 
				
			||||||
        if type_id is None and attr_id is not None:
 | 
					        if type_id is None and attr_id is not None:
 | 
				
			||||||
            from api.models.cmdb import CITypeAttribute
 | 
					            from api.models.cmdb import CITypeAttribute
 | 
				
			||||||
            type_ids = [i.type_id for i in CITypeAttribute.get_by(attr_id=attr_id, to_dict=False)]
 | 
					            type_ids = [i.type_id for i in CITypeAttribute.get_by(attr_id=attr_id, to_dict=False)]
 | 
				
			||||||
@@ -284,6 +294,7 @@ class CITypeHistoryManager(object):
 | 
				
			|||||||
                           uid=current_user.uid,
 | 
					                           uid=current_user.uid,
 | 
				
			||||||
                           attr_id=attr_id,
 | 
					                           attr_id=attr_id,
 | 
				
			||||||
                           trigger_id=trigger_id,
 | 
					                           trigger_id=trigger_id,
 | 
				
			||||||
 | 
					                           rc_id=rc_id,
 | 
				
			||||||
                           unique_constraint_id=unique_constraint_id,
 | 
					                           unique_constraint_id=unique_constraint_id,
 | 
				
			||||||
                           change=change)
 | 
					                           change=change)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,6 +78,8 @@ class ErrFormat(CommonErrFormat):
 | 
				
			|||||||
    unique_constraint_invalid = _l("Uniquely constrained attributes cannot be JSON and multi-valued")
 | 
					    unique_constraint_invalid = _l("Uniquely constrained attributes cannot be JSON and multi-valued")
 | 
				
			||||||
    ci_type_trigger_duplicate = _l("Duplicated trigger")  # 重复的触发器
 | 
					    ci_type_trigger_duplicate = _l("Duplicated trigger")  # 重复的触发器
 | 
				
			||||||
    ci_type_trigger_not_found = _l("Trigger {} does not exist")  # 触发器 {} 不存在
 | 
					    ci_type_trigger_not_found = _l("Trigger {} does not exist")  # 触发器 {} 不存在
 | 
				
			||||||
 | 
					    ci_type_reconciliation_duplicate = _l("Duplicated reconciliation rule")  # 重复的校验规则
 | 
				
			||||||
 | 
					    ci_type_reconciliation_not_found = _l("Reconciliation rule {} does not exist")  # 规则 {} 不存在
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    record_not_found = _l("Operation record {} does not exist")  # 操作记录 {} 不存在
 | 
					    record_not_found = _l("Operation record {} does not exist")  # 操作记录 {} 不存在
 | 
				
			||||||
    cannot_delete_unique = _l("Unique identifier cannot be deleted")  # 不能删除唯一标识
 | 
					    cannot_delete_unique = _l("Unique identifier cannot be deleted")  # 不能删除唯一标识
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -275,34 +275,27 @@ class AttributeValueManager(object):
 | 
				
			|||||||
            if attr.is_list:
 | 
					            if attr.is_list:
 | 
				
			||||||
                existed_attrs = value_table.get_by(attr_id=attr.id, ci_id=ci.id, to_dict=False)
 | 
					                existed_attrs = value_table.get_by(attr_id=attr.id, ci_id=ci.id, to_dict=False)
 | 
				
			||||||
                existed_values = [i.value for i in existed_attrs]
 | 
					                existed_values = [i.value for i in existed_attrs]
 | 
				
			||||||
 | 
					                added = set(value) - set(existed_values)
 | 
				
			||||||
 | 
					                deleted = set(existed_values) - set(value)
 | 
				
			||||||
 | 
					                for v in added:
 | 
				
			||||||
 | 
					                    value_table.create(ci_id=ci.id, attr_id=attr.id, value=v, flush=False, commit=False)
 | 
				
			||||||
 | 
					                    changed.append((ci.id, attr.id, OperateType.ADD, None, v, ci.type_id))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # Comparison array starts from which position changes
 | 
					 | 
				
			||||||
                min_len = min(len(value), len(existed_values))
 | 
					 | 
				
			||||||
                index = 0
 | 
					 | 
				
			||||||
                while index < min_len:
 | 
					 | 
				
			||||||
                    if value[index] != existed_values[index]:
 | 
					 | 
				
			||||||
                        break
 | 
					 | 
				
			||||||
                    index += 1
 | 
					 | 
				
			||||||
                added = value[index:]
 | 
					 | 
				
			||||||
                deleted = existed_values[index:]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                # Delete first and then add to ensure id sorting
 | 
					 | 
				
			||||||
                for v in deleted:
 | 
					                for v in deleted:
 | 
				
			||||||
                    existed_attr = existed_attrs[existed_values.index(v)]
 | 
					                    existed_attr = existed_attrs[existed_values.index(v)]
 | 
				
			||||||
                    existed_attr.delete(flush=False, commit=False)
 | 
					                    existed_attr.delete(flush=False, commit=False)
 | 
				
			||||||
                    changed.append((ci.id, attr.id, OperateType.DELETE, v, None, ci.type_id))
 | 
					                    changed.append((ci.id, attr.id, OperateType.DELETE, v, None, ci.type_id))
 | 
				
			||||||
                for v in added:
 | 
					 | 
				
			||||||
                    value_table.create(ci_id=ci.id, attr_id=attr.id, value=v, flush=False, commit=False)
 | 
					 | 
				
			||||||
                    changed.append((ci.id, attr.id, OperateType.ADD, None, v, ci.type_id))
 | 
					 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                existed_attr = value_table.get_by(attr_id=attr.id, ci_id=ci.id, first=True, to_dict=False)
 | 
					                existed_attr = value_table.get_by(attr_id=attr.id, ci_id=ci.id, first=True, to_dict=False)
 | 
				
			||||||
                existed_value = existed_attr and existed_attr.value
 | 
					                existed_value = existed_attr and existed_attr.value
 | 
				
			||||||
 | 
					                existed_value = (ValueTypeMap.serialize[attr.value_type](existed_value) if
 | 
				
			||||||
 | 
					                                 existed_value or existed_value == 0 else existed_value)
 | 
				
			||||||
                if existed_value is None and value is not None:
 | 
					                if existed_value is None and value is not None:
 | 
				
			||||||
                    value_table.create(ci_id=ci.id, attr_id=attr.id, value=value, flush=False, commit=False)
 | 
					                    value_table.create(ci_id=ci.id, attr_id=attr.id, value=value, flush=False, commit=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    changed.append((ci.id, attr.id, OperateType.ADD, None, value, ci.type_id))
 | 
					                    changed.append((ci.id, attr.id, OperateType.ADD, None, value, ci.type_id))
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    if existed_value != value:
 | 
					                    if existed_value != value and existed_attr:
 | 
				
			||||||
                        if value is None:
 | 
					                        if value is None:
 | 
				
			||||||
                            existed_attr.delete(flush=False, commit=False)
 | 
					                            existed_attr.delete(flush=False, commit=False)
 | 
				
			||||||
                        else:
 | 
					                        else:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -224,16 +224,22 @@ class RoleRelationCache(object):
 | 
				
			|||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    @flush_db
 | 
					    @flush_db
 | 
				
			||||||
    def rebuild(cls, rid, app_id):
 | 
					    def rebuild(cls, rid, app_id):
 | 
				
			||||||
        cls.clean(rid, app_id)
 | 
					        if app_id is None:
 | 
				
			||||||
 | 
					            app_ids = [None] + [i.id for i in App.get_by(to_dict=False)]
 | 
				
			||||||
        cls.get_parent_ids(rid, app_id)
 | 
					 | 
				
			||||||
        cls.get_child_ids(rid, app_id)
 | 
					 | 
				
			||||||
        resources = cls.get_resources(rid, app_id)
 | 
					 | 
				
			||||||
        if resources.get('id2perms') or resources.get('group2perms'):
 | 
					 | 
				
			||||||
            HasResourceRoleCache.add(rid, app_id)
 | 
					 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            HasResourceRoleCache.remove(rid, app_id)
 | 
					            app_ids = [app_id]
 | 
				
			||||||
        cls.get_resources2(rid, app_id)
 | 
					
 | 
				
			||||||
 | 
					        for _app_id in app_ids:
 | 
				
			||||||
 | 
					            cls.clean(rid, _app_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            cls.get_parent_ids(rid, _app_id)
 | 
				
			||||||
 | 
					            cls.get_child_ids(rid, _app_id)
 | 
				
			||||||
 | 
					            resources = cls.get_resources(rid, _app_id)
 | 
				
			||||||
 | 
					            if resources.get('id2perms') or resources.get('group2perms'):
 | 
				
			||||||
 | 
					                HasResourceRoleCache.add(rid, _app_id)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                HasResourceRoleCache.remove(rid, _app_id)
 | 
				
			||||||
 | 
					            cls.get_resources2(rid, _app_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    @flush_db
 | 
					    @flush_db
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -274,12 +274,14 @@ class PermissionCRUD(object):
 | 
				
			|||||||
                    perm2resource.setdefault(_perm, []).append(resource_id)
 | 
					                    perm2resource.setdefault(_perm, []).append(resource_id)
 | 
				
			||||||
            for _perm in perm2resource:
 | 
					            for _perm in perm2resource:
 | 
				
			||||||
                perm = PermissionCache.get(_perm, resource_type_id)
 | 
					                perm = PermissionCache.get(_perm, resource_type_id)
 | 
				
			||||||
                existeds = RolePermission.get_by(rid=rid,
 | 
					                if perm is None:
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                exists = RolePermission.get_by(rid=rid,
 | 
				
			||||||
                                               app_id=app_id,
 | 
					                                               app_id=app_id,
 | 
				
			||||||
                                               perm_id=perm.id,
 | 
					                                               perm_id=perm.id,
 | 
				
			||||||
                                               __func_in___key_resource_id=perm2resource[_perm],
 | 
					                                               __func_in___key_resource_id=perm2resource[_perm],
 | 
				
			||||||
                                               to_dict=False)
 | 
					                                               to_dict=False)
 | 
				
			||||||
                for existed in existeds:
 | 
					                for existed in exists:
 | 
				
			||||||
                    existed.deleted = True
 | 
					                    existed.deleted = True
 | 
				
			||||||
                    existed.deleted_at = datetime.datetime.now()
 | 
					                    existed.deleted_at = datetime.datetime.now()
 | 
				
			||||||
                    db.session.add(existed)
 | 
					                    db.session.add(existed)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from flask import abort
 | 
					from flask import abort
 | 
				
			||||||
from flask import current_app
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from api.extensions import db
 | 
					from api.extensions import db
 | 
				
			||||||
from api.lib.perm.acl.audit import AuditCRUD
 | 
					from api.lib.perm.acl.audit import AuditCRUD
 | 
				
			||||||
@@ -127,11 +126,18 @@ class ResourceTypeCRUD(object):
 | 
				
			|||||||
        existed_ids = [i.id for i in existed]
 | 
					        existed_ids = [i.id for i in existed]
 | 
				
			||||||
        current_ids = []
 | 
					        current_ids = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rebuild_rids = set()
 | 
				
			||||||
        for i in existed:
 | 
					        for i in existed:
 | 
				
			||||||
            if i.name not in perms:
 | 
					            if i.name not in perms:
 | 
				
			||||||
                i.soft_delete()
 | 
					                i.soft_delete(commit=False)
 | 
				
			||||||
 | 
					                for rp in RolePermission.get_by(perm_id=i.id, to_dict=False):
 | 
				
			||||||
 | 
					                    rp.soft_delete(commit=False)
 | 
				
			||||||
 | 
					                    rebuild_rids.add((rp.app_id, rp.rid))
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                current_ids.append(i.id)
 | 
					                current_ids.append(i.id)
 | 
				
			||||||
 | 
					        db.session.commit()
 | 
				
			||||||
 | 
					        for _app_id, _rid in rebuild_rids:
 | 
				
			||||||
 | 
					            role_rebuild.apply_async(args=(_rid, _app_id), queue=ACL_QUEUE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for i in perms:
 | 
					        for i in perms:
 | 
				
			||||||
            if i not in existed_names:
 | 
					            if i not in existed_names:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,12 +3,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import redis_lock
 | 
				
			||||||
import six
 | 
					import six
 | 
				
			||||||
from flask import abort
 | 
					from flask import abort
 | 
				
			||||||
from flask import current_app
 | 
					from flask import current_app
 | 
				
			||||||
from sqlalchemy import or_
 | 
					from sqlalchemy import or_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from api.extensions import db
 | 
					from api.extensions import db
 | 
				
			||||||
 | 
					from api.extensions import rd
 | 
				
			||||||
from api.lib.perm.acl.app import AppCRUD
 | 
					from api.lib.perm.acl.app import AppCRUD
 | 
				
			||||||
from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType, AuditScope
 | 
					from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType, AuditScope
 | 
				
			||||||
from api.lib.perm.acl.cache import AppCache
 | 
					from api.lib.perm.acl.cache import AppCache
 | 
				
			||||||
@@ -62,7 +64,9 @@ class RoleRelationCRUD(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        id2parents = {}
 | 
					        id2parents = {}
 | 
				
			||||||
        for i in res:
 | 
					        for i in res:
 | 
				
			||||||
            id2parents.setdefault(rid2uid.get(i.child_id, i.child_id), []).append(RoleCache.get(i.parent_id).to_dict())
 | 
					            parent = RoleCache.get(i.parent_id)
 | 
				
			||||||
 | 
					            if parent:
 | 
				
			||||||
 | 
					                id2parents.setdefault(rid2uid.get(i.child_id, i.child_id), []).append(parent.to_dict())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return id2parents
 | 
					        return id2parents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -141,6 +145,9 @@ class RoleRelationCRUD(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def add(cls, role, parent_id, child_ids, app_id):
 | 
					    def add(cls, role, parent_id, child_ids, app_id):
 | 
				
			||||||
 | 
					        with redis_lock.Lock(rd.r, "ROLE_RELATION_ADD"):
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            result = []
 | 
					            result = []
 | 
				
			||||||
            for child_id in child_ids:
 | 
					            for child_id in child_ids:
 | 
				
			||||||
                existed = RoleRelation.get_by(parent_id=parent_id, child_id=child_id, app_id=app_id)
 | 
					                existed = RoleRelation.get_by(parent_id=parent_id, child_id=child_id, app_id=app_id)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,12 +3,13 @@
 | 
				
			|||||||
import json
 | 
					import json
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from celery_once import QueueOnce
 | 
					import redis_lock
 | 
				
			||||||
from flask import current_app
 | 
					from flask import current_app
 | 
				
			||||||
from werkzeug.exceptions import BadRequest
 | 
					from werkzeug.exceptions import BadRequest
 | 
				
			||||||
from werkzeug.exceptions import NotFound
 | 
					from werkzeug.exceptions import NotFound
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from api.extensions import celery
 | 
					from api.extensions import celery
 | 
				
			||||||
 | 
					from api.extensions import rd
 | 
				
			||||||
from api.lib.decorator import flush_db
 | 
					from api.lib.decorator import flush_db
 | 
				
			||||||
from api.lib.decorator import reconnect_db
 | 
					from api.lib.decorator import reconnect_db
 | 
				
			||||||
from api.lib.perm.acl.audit import AuditCRUD
 | 
					from api.lib.perm.acl.audit import AuditCRUD
 | 
				
			||||||
@@ -25,13 +26,13 @@ from api.models.acl import Role
 | 
				
			|||||||
from api.models.acl import Trigger
 | 
					from api.models.acl import Trigger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@celery.task(name="acl.role_rebuild",
 | 
					@celery.task(name="acl.role_rebuild", queue=ACL_QUEUE, )
 | 
				
			||||||
             queue=ACL_QUEUE,)
 | 
					 | 
				
			||||||
@flush_db
 | 
					@flush_db
 | 
				
			||||||
@reconnect_db
 | 
					@reconnect_db
 | 
				
			||||||
def role_rebuild(rids, app_id):
 | 
					def role_rebuild(rids, app_id):
 | 
				
			||||||
    rids = rids if isinstance(rids, list) else [rids]
 | 
					    rids = rids if isinstance(rids, list) else [rids]
 | 
				
			||||||
    for rid in rids:
 | 
					    for rid in rids:
 | 
				
			||||||
 | 
					        with redis_lock.Lock(rd.r, "ROLE_REBUILD_{}_{}".format(rid, app_id)):
 | 
				
			||||||
            RoleRelationCache.rebuild(rid, app_id)
 | 
					            RoleRelationCache.rebuild(rid, app_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    current_app.logger.info("Role {0} App {1} rebuild..........".format(rids, app_id))
 | 
					    current_app.logger.info("Role {0} App {1} rebuild..........".format(rids, app_id))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ from api.lib.cmdb.const import RetKey
 | 
				
			|||||||
from api.lib.cmdb.perms import has_perm_for_ci
 | 
					from api.lib.cmdb.perms import has_perm_for_ci
 | 
				
			||||||
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
 | 
				
			||||||
 | 
					from api.lib.decorator import args_required
 | 
				
			||||||
from api.lib.perm.acl.acl import has_perm_from_args
 | 
					from api.lib.perm.acl.acl import has_perm_from_args
 | 
				
			||||||
from api.lib.utils import get_page
 | 
					from api.lib.utils import get_page
 | 
				
			||||||
from api.lib.utils import get_page_size
 | 
					from api.lib.utils import get_page_size
 | 
				
			||||||
@@ -254,3 +255,23 @@ class CIPasswordView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def post(self, ci_id, attr_id):
 | 
					    def post(self, ci_id, attr_id):
 | 
				
			||||||
        return self.get(ci_id, attr_id)
 | 
					        return self.get(ci_id, attr_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CIBaselineView(APIView):
 | 
				
			||||||
 | 
					    url_prefix = ("/ci/baseline", "/ci/<int:ci_id>/baseline/rollback")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @args_required("before_date")
 | 
				
			||||||
 | 
					    def get(self):
 | 
				
			||||||
 | 
					        ci_ids = handle_arg_list(request.values.get('ci_ids'))
 | 
				
			||||||
 | 
					        before_date = request.values.get('before_date')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return self.jsonify(CIManager().baseline(list(map(int, ci_ids)), before_date))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @args_required("before_date")
 | 
				
			||||||
 | 
					    def post(self, ci_id):
 | 
				
			||||||
 | 
					        if 'rollback' in request.url:
 | 
				
			||||||
 | 
					            before_date = request.values.get('before_date')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return self.jsonify(**CIManager().rollback(ci_id, before_date))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return self.get(ci_id)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,6 @@ from io import BytesIO
 | 
				
			|||||||
from flask import abort
 | 
					from flask import abort
 | 
				
			||||||
from flask import current_app
 | 
					from flask import current_app
 | 
				
			||||||
from flask import request
 | 
					from flask import request
 | 
				
			||||||
from flask import session
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
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.cache import CITypeCache
 | 
				
			||||||
@@ -23,6 +22,8 @@ from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum
 | 
				
			|||||||
from api.lib.cmdb.perms import CIFilterPermsCRUD
 | 
					from api.lib.cmdb.perms import CIFilterPermsCRUD
 | 
				
			||||||
from api.lib.cmdb.preference import PreferenceManager
 | 
					from api.lib.cmdb.preference import PreferenceManager
 | 
				
			||||||
from api.lib.cmdb.resp_format import ErrFormat
 | 
					from api.lib.cmdb.resp_format import ErrFormat
 | 
				
			||||||
 | 
					from api.lib.common_setting.decorator import perms_role_required
 | 
				
			||||||
 | 
					from api.lib.common_setting.role_perm_base import CMDBApp
 | 
				
			||||||
from api.lib.decorator import args_required
 | 
					from api.lib.decorator import args_required
 | 
				
			||||||
from api.lib.decorator import args_validate
 | 
					from api.lib.decorator import args_validate
 | 
				
			||||||
from api.lib.perm.acl.acl import ACLManager
 | 
					from api.lib.perm.acl.acl import ACLManager
 | 
				
			||||||
@@ -36,6 +37,8 @@ from api.lib.perm.auth import auth_with_app_token
 | 
				
			|||||||
from api.lib.utils import handle_arg_list
 | 
					from api.lib.utils import handle_arg_list
 | 
				
			||||||
from api.resource import APIView
 | 
					from api.resource import APIView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app_cli = CMDBApp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CITypeView(APIView):
 | 
					class CITypeView(APIView):
 | 
				
			||||||
    url_prefix = ("/ci_types", "/ci_types/<int:type_id>", "/ci_types/<string:type_name>",
 | 
					    url_prefix = ("/ci_types", "/ci_types/<int:type_id>", "/ci_types/<string:type_name>",
 | 
				
			||||||
@@ -125,7 +128,8 @@ class CITypeGroupView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(CITypeGroupManager.get(need_other, config_required))
 | 
					        return self.jsonify(CITypeGroupManager.get(need_other, config_required))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Model_Configuration,
 | 
				
			||||||
 | 
					                         app_cli.op.create_CIType_group, app_cli.admin_name)
 | 
				
			||||||
    @args_required("name")
 | 
					    @args_required("name")
 | 
				
			||||||
    @args_validate(CITypeGroupManager.cls)
 | 
					    @args_validate(CITypeGroupManager.cls)
 | 
				
			||||||
    def post(self):
 | 
					    def post(self):
 | 
				
			||||||
@@ -134,12 +138,11 @@ class CITypeGroupView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(group.to_dict())
 | 
					        return self.jsonify(group.to_dict())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Model_Configuration,
 | 
				
			||||||
 | 
					                         app_cli.op.update_CIType_group, app_cli.admin_name)
 | 
				
			||||||
    @args_validate(CITypeGroupManager.cls)
 | 
					    @args_validate(CITypeGroupManager.cls)
 | 
				
			||||||
    def put(self, gid=None):
 | 
					    def put(self, gid=None):
 | 
				
			||||||
        if "/order" in request.url:
 | 
					        if "/order" in request.url:
 | 
				
			||||||
            if RoleEnum.CONFIG not in session.get("acl", {}).get("parentRoles", []) and not is_app_admin("cmdb"):
 | 
					 | 
				
			||||||
                return abort(403, ErrFormat.role_required.format(RoleEnum.CONFIG))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            group_ids = request.values.get('group_ids')
 | 
					            group_ids = request.values.get('group_ids')
 | 
				
			||||||
            CITypeGroupManager.order(group_ids)
 | 
					            CITypeGroupManager.order(group_ids)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -152,7 +155,8 @@ class CITypeGroupView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(gid=gid)
 | 
					        return self.jsonify(gid=gid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Model_Configuration,
 | 
				
			||||||
 | 
					                         app_cli.op.delete_CIType_group, app_cli.admin_name)
 | 
				
			||||||
    def delete(self, gid):
 | 
					    def delete(self, gid):
 | 
				
			||||||
        type_ids = request.values.get("type_ids")
 | 
					        type_ids = request.values.get("type_ids")
 | 
				
			||||||
        CITypeGroupManager.delete(gid, type_ids)
 | 
					        CITypeGroupManager.delete(gid, type_ids)
 | 
				
			||||||
@@ -352,14 +356,16 @@ class CITypeAttributeGroupView(APIView):
 | 
				
			|||||||
class CITypeTemplateView(APIView):
 | 
					class CITypeTemplateView(APIView):
 | 
				
			||||||
    url_prefix = ("/ci_types/template/import", "/ci_types/template/export", "/ci_types/<int:type_id>/template/export")
 | 
					    url_prefix = ("/ci_types/template/import", "/ci_types/template/export", "/ci_types/<int:type_id>/template/export")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Model_Configuration,
 | 
				
			||||||
 | 
					                         app_cli.op.download_CIType, app_cli.admin_name)
 | 
				
			||||||
    def get(self, type_id=None):  # export
 | 
					    def get(self, type_id=None):  # export
 | 
				
			||||||
        if type_id is not None:
 | 
					        if type_id is not None:
 | 
				
			||||||
            return self.jsonify(dict(ci_type_template=CITypeTemplateManager.export_template_by_type(type_id)))
 | 
					            return self.jsonify(dict(ci_type_template=CITypeTemplateManager.export_template_by_type(type_id)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(dict(ci_type_template=CITypeTemplateManager.export_template()))
 | 
					        return self.jsonify(dict(ci_type_template=CITypeTemplateManager.export_template()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Model_Configuration,
 | 
				
			||||||
 | 
					                         app_cli.op.download_CIType, app_cli.admin_name)
 | 
				
			||||||
    def post(self):  # import
 | 
					    def post(self):  # import
 | 
				
			||||||
        tpt = request.values.get('ci_type_template') or {}
 | 
					        tpt = request.values.get('ci_type_template') or {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -379,7 +385,8 @@ class CITypeCanDefineComputed(APIView):
 | 
				
			|||||||
class CITypeTemplateFileView(APIView):
 | 
					class CITypeTemplateFileView(APIView):
 | 
				
			||||||
    url_prefix = ("/ci_types/template/import/file", "/ci_types/template/export/file")
 | 
					    url_prefix = ("/ci_types/template/import/file", "/ci_types/template/export/file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Model_Configuration,
 | 
				
			||||||
 | 
					                         app_cli.op.download_CIType, app_cli.admin_name)
 | 
				
			||||||
    def get(self):  # export
 | 
					    def get(self):  # export
 | 
				
			||||||
        tpt_json = CITypeTemplateManager.export_template()
 | 
					        tpt_json = CITypeTemplateManager.export_template()
 | 
				
			||||||
        tpt_json = dict(ci_type_template=tpt_json)
 | 
					        tpt_json = dict(ci_type_template=tpt_json)
 | 
				
			||||||
@@ -394,7 +401,8 @@ class CITypeTemplateFileView(APIView):
 | 
				
			|||||||
                              mimetype='application/json',
 | 
					                              mimetype='application/json',
 | 
				
			||||||
                              max_age=0)
 | 
					                              max_age=0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Model_Configuration,
 | 
				
			||||||
 | 
					                         app_cli.op.download_CIType, app_cli.admin_name)
 | 
				
			||||||
    def post(self):  # import
 | 
					    def post(self):  # import
 | 
				
			||||||
        f = request.files.get('file')
 | 
					        f = request.files.get('file')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,8 @@ from api.lib.cmdb.const import ResourceTypeEnum
 | 
				
			|||||||
from api.lib.cmdb.const import RoleEnum
 | 
					from api.lib.cmdb.const import RoleEnum
 | 
				
			||||||
from api.lib.cmdb.preference import PreferenceManager
 | 
					from api.lib.cmdb.preference import PreferenceManager
 | 
				
			||||||
from api.lib.cmdb.resp_format import ErrFormat
 | 
					from api.lib.cmdb.resp_format import ErrFormat
 | 
				
			||||||
 | 
					from api.lib.common_setting.decorator import perms_role_required
 | 
				
			||||||
 | 
					from api.lib.common_setting.role_perm_base import CMDBApp
 | 
				
			||||||
from api.lib.decorator import args_required
 | 
					from api.lib.decorator import args_required
 | 
				
			||||||
from api.lib.perm.acl.acl import ACLManager
 | 
					from api.lib.perm.acl.acl import ACLManager
 | 
				
			||||||
from api.lib.perm.acl.acl import has_perm_from_args
 | 
					from api.lib.perm.acl.acl import has_perm_from_args
 | 
				
			||||||
@@ -18,6 +20,8 @@ from api.lib.perm.acl.acl import is_app_admin
 | 
				
			|||||||
from api.lib.perm.acl.acl import role_required
 | 
					from api.lib.perm.acl.acl import role_required
 | 
				
			||||||
from api.resource import APIView
 | 
					from api.resource import APIView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app_cli = CMDBApp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GetChildrenView(APIView):
 | 
					class GetChildrenView(APIView):
 | 
				
			||||||
    url_prefix = ("/ci_type_relations/<int:parent_id>/children",
 | 
					    url_prefix = ("/ci_type_relations/<int:parent_id>/children",
 | 
				
			||||||
@@ -41,7 +45,8 @@ class GetParentsView(APIView):
 | 
				
			|||||||
class CITypeRelationView(APIView):
 | 
					class CITypeRelationView(APIView):
 | 
				
			||||||
    url_prefix = ("/ci_type_relations", "/ci_type_relations/<int:parent_id>/<int:child_id>")
 | 
					    url_prefix = ("/ci_type_relations", "/ci_type_relations/<int:parent_id>/<int:child_id>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Service_Tree_Definition,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    def get(self):
 | 
					    def get(self):
 | 
				
			||||||
        res, type2attributes = CITypeRelationManager.get()
 | 
					        res, type2attributes = CITypeRelationManager.get()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -69,7 +74,8 @@ class CITypeRelationView(APIView):
 | 
				
			|||||||
class CITypeRelationDelete2View(APIView):
 | 
					class CITypeRelationDelete2View(APIView):
 | 
				
			||||||
    url_prefix = "/ci_type_relations/<int:ctr_id>"
 | 
					    url_prefix = "/ci_type_relations/<int:ctr_id>"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Model_Relationships,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    def delete(self, ctr_id):
 | 
					    def delete(self, ctr_id):
 | 
				
			||||||
        CITypeRelationManager.delete(ctr_id)
 | 
					        CITypeRelationManager.delete(ctr_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,14 +3,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from flask import request
 | 
					from flask import request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from api.lib.cmdb.const import RoleEnum
 | 
					 | 
				
			||||||
from api.lib.cmdb.custom_dashboard import CustomDashboardManager
 | 
					from api.lib.cmdb.custom_dashboard import CustomDashboardManager
 | 
				
			||||||
from api.lib.cmdb.custom_dashboard import SystemConfigManager
 | 
					from api.lib.cmdb.custom_dashboard import SystemConfigManager
 | 
				
			||||||
 | 
					from api.lib.common_setting.decorator import perms_role_required
 | 
				
			||||||
 | 
					from api.lib.common_setting.role_perm_base import CMDBApp
 | 
				
			||||||
from api.lib.decorator import args_required
 | 
					from api.lib.decorator import args_required
 | 
				
			||||||
from api.lib.decorator import args_validate
 | 
					from api.lib.decorator import args_validate
 | 
				
			||||||
from api.lib.perm.acl.acl import role_required
 | 
					 | 
				
			||||||
from api.resource import APIView
 | 
					from api.resource import APIView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app_cli = CMDBApp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CustomDashboardApiView(APIView):
 | 
					class CustomDashboardApiView(APIView):
 | 
				
			||||||
    url_prefix = ("/custom_dashboard", "/custom_dashboard/<int:_id>", "/custom_dashboard/batch",
 | 
					    url_prefix = ("/custom_dashboard", "/custom_dashboard/<int:_id>", "/custom_dashboard/batch",
 | 
				
			||||||
@@ -19,7 +21,8 @@ class CustomDashboardApiView(APIView):
 | 
				
			|||||||
    def get(self):
 | 
					    def get(self):
 | 
				
			||||||
        return self.jsonify(CustomDashboardManager.get())
 | 
					        return self.jsonify(CustomDashboardManager.get())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Customized_Dashboard,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    @args_validate(CustomDashboardManager.cls)
 | 
					    @args_validate(CustomDashboardManager.cls)
 | 
				
			||||||
    def post(self):
 | 
					    def post(self):
 | 
				
			||||||
        if request.url.endswith("/preview"):
 | 
					        if request.url.endswith("/preview"):
 | 
				
			||||||
@@ -32,7 +35,8 @@ class CustomDashboardApiView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(res)
 | 
					        return self.jsonify(res)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Customized_Dashboard,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    @args_validate(CustomDashboardManager.cls)
 | 
					    @args_validate(CustomDashboardManager.cls)
 | 
				
			||||||
    def put(self, _id=None):
 | 
					    def put(self, _id=None):
 | 
				
			||||||
        if _id is not None:
 | 
					        if _id is not None:
 | 
				
			||||||
@@ -47,7 +51,8 @@ class CustomDashboardApiView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(id2options=request.values.get('id2options'))
 | 
					        return self.jsonify(id2options=request.values.get('id2options'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Customized_Dashboard,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    def delete(self, _id):
 | 
					    def delete(self, _id):
 | 
				
			||||||
        CustomDashboardManager.delete(_id)
 | 
					        CustomDashboardManager.delete(_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,12 +62,14 @@ class CustomDashboardApiView(APIView):
 | 
				
			|||||||
class SystemConfigApiView(APIView):
 | 
					class SystemConfigApiView(APIView):
 | 
				
			||||||
    url_prefix = ("/system_config",)
 | 
					    url_prefix = ("/system_config",)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Service_Tree_Definition,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    @args_required("name", value_required=True)
 | 
					    @args_required("name", value_required=True)
 | 
				
			||||||
    def get(self):
 | 
					    def get(self):
 | 
				
			||||||
        return self.jsonify(SystemConfigManager.get(request.values['name']))
 | 
					        return self.jsonify(SystemConfigManager.get(request.values['name']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Service_Tree_Definition,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    @args_validate(SystemConfigManager.cls)
 | 
					    @args_validate(SystemConfigManager.cls)
 | 
				
			||||||
    @args_required("name", value_required=True)
 | 
					    @args_required("name", value_required=True)
 | 
				
			||||||
    @args_required("option", value_required=True)
 | 
					    @args_required("option", value_required=True)
 | 
				
			||||||
@@ -74,7 +81,8 @@ class SystemConfigApiView(APIView):
 | 
				
			|||||||
    def put(self, _id=None):
 | 
					    def put(self, _id=None):
 | 
				
			||||||
        return self.post()
 | 
					        return self.post()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Service_Tree_Definition,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    @args_required("name")
 | 
					    @args_required("name")
 | 
				
			||||||
    def delete(self):
 | 
					    def delete(self):
 | 
				
			||||||
        CustomDashboardManager.delete(request.values['name'])
 | 
					        CustomDashboardManager.delete(request.values['name'])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,28 +5,29 @@ import datetime
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from flask import abort
 | 
					from flask import abort
 | 
				
			||||||
from flask import request
 | 
					from flask import request
 | 
				
			||||||
from flask import session
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from api.lib.cmdb.ci import CIManager
 | 
					from api.lib.cmdb.ci import CIManager
 | 
				
			||||||
from api.lib.cmdb.const import PermEnum
 | 
					from api.lib.cmdb.const import PermEnum
 | 
				
			||||||
from api.lib.cmdb.const import ResourceTypeEnum
 | 
					from api.lib.cmdb.const import ResourceTypeEnum
 | 
				
			||||||
from api.lib.cmdb.const import RoleEnum
 | 
					 | 
				
			||||||
from api.lib.cmdb.history import AttributeHistoryManger
 | 
					from api.lib.cmdb.history import AttributeHistoryManger
 | 
				
			||||||
from api.lib.cmdb.history import CITriggerHistoryManager
 | 
					from api.lib.cmdb.history import CITriggerHistoryManager
 | 
				
			||||||
from api.lib.cmdb.history import CITypeHistoryManager
 | 
					from api.lib.cmdb.history import CITypeHistoryManager
 | 
				
			||||||
from api.lib.cmdb.resp_format import ErrFormat
 | 
					from api.lib.cmdb.resp_format import ErrFormat
 | 
				
			||||||
 | 
					from api.lib.common_setting.decorator import perms_role_required
 | 
				
			||||||
 | 
					from api.lib.common_setting.role_perm_base import CMDBApp
 | 
				
			||||||
from api.lib.perm.acl.acl import has_perm_from_args
 | 
					from api.lib.perm.acl.acl import has_perm_from_args
 | 
				
			||||||
from api.lib.perm.acl.acl import is_app_admin
 | 
					 | 
				
			||||||
from api.lib.perm.acl.acl import role_required
 | 
					 | 
				
			||||||
from api.lib.utils import get_page
 | 
					from api.lib.utils import get_page
 | 
				
			||||||
from api.lib.utils import get_page_size
 | 
					from api.lib.utils import get_page_size
 | 
				
			||||||
from api.resource import APIView
 | 
					from api.resource import APIView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app_cli = CMDBApp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RecordView(APIView):
 | 
					class RecordView(APIView):
 | 
				
			||||||
    url_prefix = ("/history/records/attribute", "/history/records/relation")
 | 
					    url_prefix = ("/history/records/attribute", "/history/records/relation")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Operation_Audit,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    def get(self):
 | 
					    def get(self):
 | 
				
			||||||
        page = get_page(request.values.get("page", 1))
 | 
					        page = get_page(request.values.get("page", 1))
 | 
				
			||||||
        page_size = get_page_size(request.values.get("page_size"))
 | 
					        page_size = get_page_size(request.values.get("page_size"))
 | 
				
			||||||
@@ -80,18 +81,21 @@ class CIHistoryView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CITriggerHistoryView(APIView):
 | 
					class CITriggerHistoryView(APIView):
 | 
				
			||||||
    url_prefix = ("/history/ci_triggers/<int:ci_id>", "/history/ci_triggers")
 | 
					    url_prefix = ("/history/ci_triggers/<int:ci_id>",)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @has_perm_from_args("ci_id", ResourceTypeEnum.CI, PermEnum.READ, CIManager.get_type_name)
 | 
					    @has_perm_from_args("ci_id", ResourceTypeEnum.CI, PermEnum.READ, CIManager.get_type_name)
 | 
				
			||||||
    def get(self, ci_id=None):
 | 
					    def get(self, ci_id):
 | 
				
			||||||
        if ci_id is not None:
 | 
					 | 
				
			||||||
        result = CITriggerHistoryManager.get_by_ci_id(ci_id)
 | 
					        result = CITriggerHistoryManager.get_by_ci_id(ci_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(result)
 | 
					        return self.jsonify(result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if RoleEnum.CONFIG not in session.get("acl", {}).get("parentRoles", []) and not is_app_admin("cmdb"):
 | 
					 | 
				
			||||||
            return abort(403, ErrFormat.role_required.format(RoleEnum.CONFIG))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CIsTriggerHistoryView(APIView):
 | 
				
			||||||
 | 
					    url_prefix = ("/history/ci_triggers",)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Operation_Audit,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
 | 
					    def get(self):
 | 
				
			||||||
        type_id = request.values.get("type_id")
 | 
					        type_id = request.values.get("type_id")
 | 
				
			||||||
        trigger_id = request.values.get("trigger_id")
 | 
					        trigger_id = request.values.get("trigger_id")
 | 
				
			||||||
        operate_type = request.values.get("operate_type")
 | 
					        operate_type = request.values.get("operate_type")
 | 
				
			||||||
@@ -115,7 +119,8 @@ class CITriggerHistoryView(APIView):
 | 
				
			|||||||
class CITypeHistoryView(APIView):
 | 
					class CITypeHistoryView(APIView):
 | 
				
			||||||
    url_prefix = "/history/ci_types"
 | 
					    url_prefix = "/history/ci_types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Operation_Audit,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    def get(self):
 | 
					    def get(self):
 | 
				
			||||||
        type_id = request.values.get("type_id")
 | 
					        type_id = request.values.get("type_id")
 | 
				
			||||||
        username = request.values.get("username")
 | 
					        username = request.values.get("username")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,20 +8,22 @@ from flask import request
 | 
				
			|||||||
from api.lib.cmdb.ci_type import CITypeManager
 | 
					from api.lib.cmdb.ci_type import CITypeManager
 | 
				
			||||||
from api.lib.cmdb.const import PermEnum
 | 
					from api.lib.cmdb.const import PermEnum
 | 
				
			||||||
from api.lib.cmdb.const import ResourceTypeEnum
 | 
					from api.lib.cmdb.const import ResourceTypeEnum
 | 
				
			||||||
from api.lib.cmdb.const import RoleEnum
 | 
					 | 
				
			||||||
from api.lib.cmdb.perms import CIFilterPermsCRUD
 | 
					from api.lib.cmdb.perms import CIFilterPermsCRUD
 | 
				
			||||||
from api.lib.cmdb.preference import PreferenceManager
 | 
					from api.lib.cmdb.preference import PreferenceManager
 | 
				
			||||||
from api.lib.cmdb.resp_format import ErrFormat
 | 
					from api.lib.cmdb.resp_format import ErrFormat
 | 
				
			||||||
 | 
					from api.lib.common_setting.decorator import perms_role_required
 | 
				
			||||||
 | 
					from api.lib.common_setting.role_perm_base import CMDBApp
 | 
				
			||||||
from api.lib.decorator import args_required
 | 
					from api.lib.decorator import args_required
 | 
				
			||||||
from api.lib.decorator import args_validate
 | 
					from api.lib.decorator import args_validate
 | 
				
			||||||
from api.lib.perm.acl.acl import ACLManager
 | 
					from api.lib.perm.acl.acl import ACLManager
 | 
				
			||||||
from api.lib.perm.acl.acl import has_perm_from_args
 | 
					from api.lib.perm.acl.acl import has_perm_from_args
 | 
				
			||||||
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 role_required
 | 
					 | 
				
			||||||
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 handle_arg_list
 | 
				
			||||||
from api.resource import APIView
 | 
					from api.resource import APIView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app_cli = CMDBApp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PreferenceShowCITypesView(APIView):
 | 
					class PreferenceShowCITypesView(APIView):
 | 
				
			||||||
    url_prefix = ("/preference/ci_types", "/preference/ci_types2")
 | 
					    url_prefix = ("/preference/ci_types", "/preference/ci_types2")
 | 
				
			||||||
@@ -104,7 +106,8 @@ class PreferenceRelationApiView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(views=views, id2type=id2type, name2id=name2id)
 | 
					        return self.jsonify(views=views, id2type=id2type, name2id=name2id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Service_Tree_Definition,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    @args_required("name")
 | 
					    @args_required("name")
 | 
				
			||||||
    @args_required("cr_ids")
 | 
					    @args_required("cr_ids")
 | 
				
			||||||
    @args_validate(PreferenceManager.pref_rel_cls)
 | 
					    @args_validate(PreferenceManager.pref_rel_cls)
 | 
				
			||||||
@@ -118,14 +121,16 @@ class PreferenceRelationApiView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(views=views, id2type=id2type, name2id=name2id)
 | 
					        return self.jsonify(views=views, id2type=id2type, name2id=name2id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Service_Tree_Definition,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    @args_required("name")
 | 
					    @args_required("name")
 | 
				
			||||||
    def put(self, _id):
 | 
					    def put(self, _id):
 | 
				
			||||||
        views, id2type, name2id = PreferenceManager.create_or_update_relation_view(_id=_id, **request.values)
 | 
					        views, id2type, name2id = PreferenceManager.create_or_update_relation_view(_id=_id, **request.values)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(views=views, id2type=id2type, name2id=name2id)
 | 
					        return self.jsonify(views=views, id2type=id2type, name2id=name2id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Service_Tree_Definition,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    @args_required("name")
 | 
					    @args_required("name")
 | 
				
			||||||
    def delete(self):
 | 
					    def delete(self):
 | 
				
			||||||
        name = request.values.get("name")
 | 
					        name = request.values.get("name")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,14 +4,16 @@
 | 
				
			|||||||
from flask import abort
 | 
					from flask import abort
 | 
				
			||||||
from flask import request
 | 
					from flask import request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from api.lib.cmdb.const import RoleEnum
 | 
					 | 
				
			||||||
from api.lib.cmdb.relation_type import RelationTypeManager
 | 
					from api.lib.cmdb.relation_type import RelationTypeManager
 | 
				
			||||||
from api.lib.cmdb.resp_format import ErrFormat
 | 
					from api.lib.cmdb.resp_format import ErrFormat
 | 
				
			||||||
 | 
					from api.lib.common_setting.decorator import perms_role_required
 | 
				
			||||||
 | 
					from api.lib.common_setting.role_perm_base import CMDBApp
 | 
				
			||||||
from api.lib.decorator import args_required
 | 
					from api.lib.decorator import args_required
 | 
				
			||||||
from api.lib.decorator import args_validate
 | 
					from api.lib.decorator import args_validate
 | 
				
			||||||
from api.lib.perm.acl.acl import role_required
 | 
					 | 
				
			||||||
from api.resource import APIView
 | 
					from api.resource import APIView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app_cli = CMDBApp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RelationTypeView(APIView):
 | 
					class RelationTypeView(APIView):
 | 
				
			||||||
    url_prefix = ("/relation_types", "/relation_types/<int:rel_id>")
 | 
					    url_prefix = ("/relation_types", "/relation_types/<int:rel_id>")
 | 
				
			||||||
@@ -19,7 +21,8 @@ class RelationTypeView(APIView):
 | 
				
			|||||||
    def get(self):
 | 
					    def get(self):
 | 
				
			||||||
        return self.jsonify([i.to_dict() for i in RelationTypeManager.get_all()])
 | 
					        return self.jsonify([i.to_dict() for i in RelationTypeManager.get_all()])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Relationship_Types,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    @args_required("name")
 | 
					    @args_required("name")
 | 
				
			||||||
    @args_validate(RelationTypeManager.cls)
 | 
					    @args_validate(RelationTypeManager.cls)
 | 
				
			||||||
    def post(self):
 | 
					    def post(self):
 | 
				
			||||||
@@ -28,7 +31,8 @@ class RelationTypeView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(rel.to_dict())
 | 
					        return self.jsonify(rel.to_dict())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Relationship_Types,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    @args_required("name")
 | 
					    @args_required("name")
 | 
				
			||||||
    @args_validate(RelationTypeManager.cls)
 | 
					    @args_validate(RelationTypeManager.cls)
 | 
				
			||||||
    def put(self, rel_id):
 | 
					    def put(self, rel_id):
 | 
				
			||||||
@@ -37,7 +41,8 @@ class RelationTypeView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return self.jsonify(rel.to_dict())
 | 
					        return self.jsonify(rel.to_dict())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @role_required(RoleEnum.CONFIG)
 | 
					    @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.Relationship_Types,
 | 
				
			||||||
 | 
					                         app_cli.op.read, app_cli.admin_name)
 | 
				
			||||||
    def delete(self, rel_id):
 | 
					    def delete(self, rel_id):
 | 
				
			||||||
        RelationTypeManager.delete(rel_id)
 | 
					        RelationTypeManager.delete(rel_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user