diff --git a/api/lib/cmdb/preference.py b/api/lib/cmdb/preference.py index ae18acd..a897252 100644 --- a/api/lib/cmdb/preference.py +++ b/api/lib/cmdb/preference.py @@ -1,5 +1,7 @@ # -*- coding:utf-8 -*- +import json + import six import toposort from flask import abort @@ -113,21 +115,28 @@ class PreferenceManager(object): views = PreferenceRelationView.get_by(to_dict=True) result = dict() for view in views: - result.setdefault(view['name'], []).append(view) + result.setdefault(view['name'], []).extend(json.loads(view['cr_ids'])) + id2type = dict() for view_name in result: - result[view_name] = toposort.toposort_flatten({i['child_id']: {i['parent_id']} for i in result[view_name]}) + result[view_name] = toposort.toposort_flatten( + {i['child_id']: {i['parent_id']} for i in result[view_name]}) + for i in result[view_name]: + id2type[i['parent_id']] = None + id2type[i['child']] = None - return result + for type_id in id2type: + id2type[type_id] = CITypeCache.get(type_id).to_dict() - @staticmethod - def create_or_update_relation_view(name, parent_id, child_id): - existed = PreferenceRelationView.get_by(name=name, parent_id=parent_id, child_id=child_id, - to_dict=False, first=True) + return result, id2type + + @classmethod + def create_or_update_relation_view(cls, name, cr_ids): + existed = PreferenceRelationView.get_by(name=name, to_dict=False, first=True) if existed is None: - return PreferenceRelationView.create(name=name, parent_id=parent_id, child_id=child_id) + return PreferenceRelationView.create(name=name, cr_ids=json.dumps(cr_ids)) - return existed + return cls.get_relation_view() @staticmethod def delete_relation_view(name): diff --git a/api/lib/cmdb/search/ci/db/search.py b/api/lib/cmdb/search/ci/db/search.py index b0cd266..63f7fb0 100644 --- a/api/lib/cmdb/search/ci/db/search.py +++ b/api/lib/cmdb/search/ci/db/search.py @@ -135,12 +135,12 @@ class Search(object): elif self.type_id_list: self.query_sql = "SELECT B.ci_id FROM ({0}) AS B {1}".format( query_sql, - "INNER JOIN c_cis on c_cis.id=B.ci_id WHERE c_cis.type_id in ({0}) ".format( + "INNER JOIN c_cis on c_cis.id=B.ci_id WHERE c_cis.type_id IN ({0}) ".format( ",".join(self.type_id_list))) return ret_sql.format( query_sql, - "INNER JOIN c_cis on c_cis.id=B.ci_id WHERE c_cis.type_id in ({3}) " + "INNER JOIN c_cis on c_cis.id=B.ci_id WHERE c_cis.type_id IN ({3}) " "ORDER BY B.ci_id {1} LIMIT {0:d}, {2};".format( (self.page - 1) * self.count, sort_type, self.count, ",".join(self.type_id_list))) @@ -174,12 +174,12 @@ class Search(object): self.query_sql = """SELECT C.ci_id FROM ({0}) AS C INNER JOIN c_cis on c_cis.id=C.ci_id - WHERE c_cis.type_id in ({1})""".format(new_table, ",".join(self.type_id_list)) + WHERE c_cis.type_id IN ({1})""".format(new_table, ",".join(self.type_id_list)) return """SELECT SQL_CALC_FOUND_ROWS DISTINCT C.ci_id, C.value FROM ({0}) AS C INNER JOIN c_cis on c_cis.id=C.ci_id - WHERE c_cis.type_id in ({4}) + WHERE c_cis.type_id IN ({4}) ORDER BY C.value {2} LIMIT {1:d}, {3};""".format(new_table, (self.page - 1) * self.count, @@ -289,7 +289,7 @@ class Search(object): def _filter_ids(self, query_sql): if self.ci_ids: - return "SELECT * FROM ({0}) AS IN_QUERY WHERE IN_QUERY.ci_id in ({1})".format( + return "SELECT * FROM ({0}) AS IN_QUERY WHERE IN_QUERY.ci_id IN ({1})".format( query_sql, ",".join(list(map(str, self.ci_ids)))) return query_sql diff --git a/api/lib/database.py b/api/lib/database.py index cc43a56..3b402a3 100644 --- a/api/lib/database.py +++ b/api/lib/database.py @@ -69,7 +69,7 @@ class CRUDMixin(FormatMixin): @classmethod def get_by_id(cls, _id): if any((isinstance(_id, six.string_types) and _id.isdigit(), - isinstance(_id, (int, float))), ): + isinstance(_id, (int, long, float))), ): return getattr(cls, "query").get(int(_id)) or None @classmethod diff --git a/api/models/cmdb.py b/api/models/cmdb.py index bdf5be1..5b8dec9 100644 --- a/api/models/cmdb.py +++ b/api/models/cmdb.py @@ -307,5 +307,4 @@ class PreferenceRelationView(Model): __tablename__ = "c_preference_relation_views" name = db.Column(db.String(8), index=True, nullable=False) - parent_id = db.Column(db.Integer, db.ForeignKey("c_ci_types.id"), nullable=False) - child_id = db.Column(db.Integer, db.ForeignKey("c_ci_types.id"), nullable=False) + cr_ids = db.Column(db.TEXT) # [{parent_id: x, child_id: y}] TODO: JSON diff --git a/api/views/cmdb/preference.py b/api/views/cmdb/preference.py index e54b7d4..685b3fd 100644 --- a/api/views/cmdb/preference.py +++ b/api/views/cmdb/preference.py @@ -4,10 +4,11 @@ from flask import request from api.lib.cmdb.ci_type import CITypeManager -from api.lib.cmdb.const import ResourceType, PermEnum +from api.lib.cmdb.const import ResourceType, PermEnum, RoleEnum from api.lib.cmdb.preference import PreferenceManager 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 role_required from api.lib.utils import handle_arg_list from api.resource import APIView @@ -18,6 +19,7 @@ class PreferenceShowCITypesView(APIView): def get(self): instance = request.values.get("instance") tree = request.values.get("tree") + return self.jsonify(PreferenceManager.get_types(instance, tree)) @@ -26,6 +28,7 @@ class PreferenceShowAttributesView(APIView): def get(self, id_or_name): is_subscribed, attributes = PreferenceManager.get_show_attributes(id_or_name) + return self.jsonify(attributes=attributes, is_subscribed=is_subscribed) @has_perm_from_args("id_or_name", ResourceType.CI, PermEnum.READ, CITypeManager.get_name_by_id) @@ -35,12 +38,13 @@ class PreferenceShowAttributesView(APIView): attr_list = handle_arg_list(request.values.get("attr", "")) orders = list(range(len(attr_list))) PreferenceManager.create_or_update_show_attributes(id_or_name, list(zip(attr_list, orders))) + return self.jsonify(type_id=id_or_name, attr_order=list(zip(attr_list, orders))) @has_perm_from_args("id_or_name", ResourceType.CI, PermEnum.READ, CITypeManager.get_name_by_id) def put(self, id_or_name): - self.post(id_or_name) + return self.post(id_or_name) class PreferenceTreeApiView(APIView): @@ -56,33 +60,36 @@ class PreferenceTreeApiView(APIView): type_id = request.values.get("type_id") levels = handle_arg_list(request.values.get("levels")) res = PreferenceManager.create_or_update_tree_view(type_id, levels) + return self.jsonify(res and res.to_dict() or {}) def put(self): - self.post() + return self.post() class PreferenceRelationApiView(APIView): url_prefix = "/preference/relation/view" def get(self): - return self.jsonify(PreferenceManager.get_relation_view()) + views, id2type = PreferenceManager.get_relation_view() - @has_perm_from_args("parent_id", ResourceType.CI, PermEnum.READ, CITypeManager.get_name_by_id) - @has_perm_from_args("child_id", ResourceType.CI, PermEnum.READ, CITypeManager.get_name_by_id) + return self.jsonify(views=views, id2type=id2type) + + @role_required(RoleEnum.CONFIG) @args_required("name") def post(self): name = request.values.get("name") - parent_id = request.values.get("parent_id") - child_id = request.values.get("child_id") - res = PreferenceManager.create_or_update_relation_view(name, parent_id, child_id) - return self.jsonify(res.to_dict()) + cr_ids = request.values.get("cr_ids") + res = PreferenceManager.create_or_update_relation_view(name, cr_ids) + + return self.jsonify(res) def put(self): - self.post() + return self.post() @args_required("name") def delete(self): name = request.values.get("name") PreferenceManager.delete_relation_view(name) + return self.jsonify(name=name)