mirror of
https://github.com/veops/cmdb.git
synced 2025-08-08 19:03:29 +08:00
前后端全面升级
This commit is contained in:
@@ -6,9 +6,9 @@ from flask import current_app
|
||||
from flask import request
|
||||
|
||||
from api.lib.cmdb.attribute import AttributeManager
|
||||
from api.lib.cmdb.const import RoleEnum
|
||||
from api.lib.cmdb.resp_format import ErrFormat
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.perm.acl.acl import role_required
|
||||
from api.lib.decorator import args_validate
|
||||
from api.lib.utils import get_page
|
||||
from api.lib.utils import get_page_size
|
||||
from api.lib.utils import handle_arg_list
|
||||
@@ -42,24 +42,30 @@ class AttributeView(APIView):
|
||||
attr_dict = attr_manager.get_attribute_by_name(attr_name)
|
||||
if attr_dict is None:
|
||||
attr_dict = attr_manager.get_attribute_by_alias(attr_name)
|
||||
|
||||
if not attr_dict:
|
||||
return abort(404, ErrFormat.attribute_not_found.format("name={}".format(attr_name)))
|
||||
elif attr_id is not None:
|
||||
attr_dict = attr_manager.get_attribute_by_id(attr_id)
|
||||
if attr_dict is not None:
|
||||
return self.jsonify(attribute=attr_dict)
|
||||
abort(404, "Attribute is not found")
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
if not attr_dict:
|
||||
return abort(404, ErrFormat.attribute_not_found.format("name={}".format(attr_name)))
|
||||
|
||||
return self.jsonify(attribute=attr_dict)
|
||||
|
||||
@args_required("name")
|
||||
@args_validate(AttributeManager.cls)
|
||||
def post(self):
|
||||
choice_value = handle_arg_list(request.values.get("choice_value"))
|
||||
params = request.values
|
||||
params["choice_value"] = choice_value
|
||||
|
||||
current_app.logger.debug(params)
|
||||
|
||||
attr_id = AttributeManager.add(**params)
|
||||
return self.jsonify(attr_id=attr_id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_validate(AttributeManager.cls)
|
||||
def put(self, attr_id):
|
||||
choice_value = handle_arg_list(request.values.get("choice_value"))
|
||||
params = request.values
|
||||
@@ -68,7 +74,6 @@ class AttributeView(APIView):
|
||||
AttributeManager().update(attr_id, **params)
|
||||
return self.jsonify(attr_id=attr_id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def delete(self, attr_id):
|
||||
attr_name = AttributeManager.delete(attr_id)
|
||||
return self.jsonify(message="attribute {0} deleted".format(attr_name))
|
||||
|
236
cmdb-api/api/views/cmdb/auto_discovery.py
Normal file
236
cmdb-api/api/views/cmdb/auto_discovery.py
Normal file
@@ -0,0 +1,236 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
import json
|
||||
from io import BytesIO
|
||||
|
||||
from flask import abort
|
||||
from flask import current_app
|
||||
from flask import g
|
||||
from flask import request
|
||||
|
||||
from api.lib.cmdb.auto_discovery.auto_discovery import AutoDiscoveryCICRUD
|
||||
from api.lib.cmdb.auto_discovery.auto_discovery import AutoDiscoveryCITypeCRUD
|
||||
from api.lib.cmdb.auto_discovery.auto_discovery import AutoDiscoveryHTTPManager
|
||||
from api.lib.cmdb.auto_discovery.auto_discovery import AutoDiscoveryRuleCRUD
|
||||
from api.lib.cmdb.auto_discovery.auto_discovery import AutoDiscoverySNMPManager
|
||||
from api.lib.cmdb.auto_discovery.const import DEFAULT_HTTP
|
||||
from api.lib.cmdb.const import PermEnum
|
||||
from api.lib.cmdb.const import ResourceTypeEnum
|
||||
from api.lib.cmdb.resp_format import ErrFormat
|
||||
from api.lib.cmdb.search import SearchError
|
||||
from api.lib.cmdb.search.ci import search
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.decorator import args_validate
|
||||
from api.lib.perm.acl.acl import has_perm_from_args
|
||||
from api.lib.utils import AESCrypto
|
||||
from api.lib.utils import get_page
|
||||
from api.lib.utils import get_page_size
|
||||
from api.lib.utils import handle_arg_list
|
||||
from api.resource import APIView
|
||||
|
||||
|
||||
class AutoDiscoveryRuleView(APIView):
|
||||
url_prefix = ("/adr", "/adr/<int:adr_id>")
|
||||
|
||||
def get(self):
|
||||
_, res = AutoDiscoveryRuleCRUD.search(page=1, page_size=100000, **request.values)
|
||||
|
||||
rebuild = False
|
||||
exists = {i['name'] for i in res}
|
||||
for i in DEFAULT_HTTP:
|
||||
if i['name'] not in exists:
|
||||
AutoDiscoveryRuleCRUD().add(**i)
|
||||
rebuild = True
|
||||
|
||||
if rebuild:
|
||||
_, res = AutoDiscoveryRuleCRUD.search(page=1, page_size=100000, **request.values)
|
||||
|
||||
return self.jsonify(res)
|
||||
|
||||
@args_required("name", value_required=True)
|
||||
@args_validate(AutoDiscoveryRuleCRUD.cls)
|
||||
def post(self):
|
||||
return self.jsonify(AutoDiscoveryRuleCRUD().add(**request.values).to_dict())
|
||||
|
||||
@args_validate(AutoDiscoveryRuleCRUD.cls)
|
||||
def put(self, adr_id):
|
||||
return self.jsonify(AutoDiscoveryRuleCRUD().update(adr_id, **request.values).to_dict())
|
||||
|
||||
def delete(self, adr_id):
|
||||
AutoDiscoveryRuleCRUD().delete(adr_id)
|
||||
|
||||
return self.jsonify(adr_id=adr_id)
|
||||
|
||||
|
||||
class AutoDiscoveryRuleTemplateFileView(APIView):
|
||||
url_prefix = ("/adr/template/import/file", "/adr/template/export/file")
|
||||
|
||||
def get(self): # export
|
||||
adr_tpt = AutoDiscoveryRuleCRUD().get_by_inner()
|
||||
adr_tpt = dict(auto_discovery_rules=adr_tpt)
|
||||
|
||||
bf = BytesIO()
|
||||
bf.write(bytes(json.dumps(adr_tpt).encode('utf-8')))
|
||||
bf.seek(0)
|
||||
|
||||
return self.send_file(bf,
|
||||
as_attachment=True,
|
||||
attachment_filename="cmdb_auto_discovery.json",
|
||||
mimetype='application/json',
|
||||
cache_timeout=0)
|
||||
|
||||
def post(self):
|
||||
f = request.files.get('file')
|
||||
|
||||
if f is None:
|
||||
return abort(400, ErrFormat.argument_file_not_found)
|
||||
|
||||
content = f.read()
|
||||
try:
|
||||
content = json.loads(content)
|
||||
except:
|
||||
return abort(400, ErrFormat.invalid_json)
|
||||
tpt = content.get('auto_discovery_rules')
|
||||
|
||||
AutoDiscoveryRuleCRUD().import_template(tpt)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class AutoDiscoveryRuleHTTPView(APIView):
|
||||
url_prefix = ("/adr/http/<string:name>/categories", "/adr/http/<string:name>/attributes",
|
||||
"/adr/snmp/<string:name>/attributes")
|
||||
|
||||
def get(self, name):
|
||||
if "snmp" in request.url:
|
||||
return self.jsonify(AutoDiscoverySNMPManager.get_attributes())
|
||||
|
||||
if "attributes" in request.url:
|
||||
category = request.values.get('category')
|
||||
return self.jsonify(AutoDiscoveryHTTPManager.get_attributes(name, category))
|
||||
|
||||
return self.jsonify(AutoDiscoveryHTTPManager.get_categories(name))
|
||||
|
||||
|
||||
class AutoDiscoveryCITypeView(APIView):
|
||||
url_prefix = ("/adt/ci_types/<int:type_id>", "/adt/<int:adt_id>")
|
||||
|
||||
def get(self, type_id):
|
||||
_, res = AutoDiscoveryCITypeCRUD.search(page=1, page_size=100000, type_id=type_id, **request.values)
|
||||
for i in res:
|
||||
if isinstance(i.get("extra_option"), dict) and i['extra_option'].get('secret'):
|
||||
if not (g.user.username == "cmdb_agent" or g.user.uid == i['uid']):
|
||||
i['extra_option'].pop('secret', None)
|
||||
else:
|
||||
i['extra_option']['secret'] = AESCrypto.decrypt(i['extra_option']['secret'])
|
||||
|
||||
return self.jsonify(res)
|
||||
|
||||
@args_validate(AutoDiscoveryCITypeCRUD.cls)
|
||||
def post(self, type_id):
|
||||
if not request.values.get('interval'):
|
||||
request.values.pop('interval', None)
|
||||
|
||||
return self.jsonify(AutoDiscoveryCITypeCRUD().add(type_id=type_id, **request.values).to_dict())
|
||||
|
||||
@args_validate(AutoDiscoveryCITypeCRUD.cls)
|
||||
def put(self, adt_id):
|
||||
if not request.values.get('interval'):
|
||||
request.values.pop('interval', None)
|
||||
|
||||
return self.jsonify(AutoDiscoveryCITypeCRUD().update(adt_id, **request.values).to_dict())
|
||||
|
||||
def delete(self, adt_id):
|
||||
AutoDiscoveryCITypeCRUD().delete(adt_id)
|
||||
|
||||
return self.jsonify(adt_id=adt_id)
|
||||
|
||||
|
||||
class AutoDiscoveryCIView(APIView):
|
||||
url_prefix = ("/adc", "/adc/<int:adc_id>", "/adc/ci_types/<int:type_id>/attributes", "/adc/ci_types")
|
||||
|
||||
def get(self, type_id=None):
|
||||
if "attributes" in request.url:
|
||||
return self.jsonify(AutoDiscoveryCICRUD.get_attributes_by_type_id(type_id))
|
||||
elif "ci_types" in request.url:
|
||||
need_other = request.values.get("need_other")
|
||||
return self.jsonify(AutoDiscoveryCICRUD.get_ci_types(need_other))
|
||||
|
||||
page = get_page(request.values.pop('page', 1))
|
||||
page_size = get_page_size(request.values.pop('page_size', None))
|
||||
fl = handle_arg_list(request.values.get('fl'))
|
||||
numfound, res = AutoDiscoveryCICRUD.search(page=page, page_size=page_size, fl=fl, **request.values)
|
||||
|
||||
return self.jsonify(page=page,
|
||||
page_size=page_size,
|
||||
numfound=numfound,
|
||||
total=len(res),
|
||||
result=res)
|
||||
|
||||
@args_validate(AutoDiscoveryCICRUD.cls)
|
||||
@args_required("type_id")
|
||||
@args_required("adt_id")
|
||||
@args_required("instance")
|
||||
def post(self):
|
||||
request.values.pop("_key", None)
|
||||
request.values.pop("_secret", None)
|
||||
|
||||
return self.jsonify(AutoDiscoveryCICRUD().upsert(**request.values).to_dict())
|
||||
|
||||
def put(self):
|
||||
return self.post()
|
||||
|
||||
@has_perm_from_args("adc_id", ResourceTypeEnum.CI, PermEnum.DELETE, AutoDiscoveryCICRUD.get_type_name)
|
||||
def delete(self, adc_id):
|
||||
AutoDiscoveryCICRUD().delete(adc_id)
|
||||
|
||||
return self.jsonify(adc_id=adc_id)
|
||||
|
||||
|
||||
class AutoDiscoveryCIDelete2View(APIView):
|
||||
url_prefix = ("/adc",)
|
||||
|
||||
def delete(self):
|
||||
type_id = request.values.get('type_id')
|
||||
unique_value = request.values.get('unique_value')
|
||||
|
||||
AutoDiscoveryCICRUD.delete2(type_id, unique_value)
|
||||
|
||||
return self.jsonify(type_id=type_id, unique_value=unique_value)
|
||||
|
||||
|
||||
class AutoDiscoveryCIAcceptView(APIView):
|
||||
url_prefix = ("/adc/<int:adc_id>/accept",)
|
||||
|
||||
@has_perm_from_args("adc_id", ResourceTypeEnum.CI, PermEnum.ADD, AutoDiscoveryCICRUD.get_type_name)
|
||||
def put(self, adc_id):
|
||||
AutoDiscoveryCICRUD.accept(None, adc_id=adc_id)
|
||||
|
||||
return self.jsonify(adc_id=adc_id)
|
||||
|
||||
|
||||
class AutoDiscoveryRuleSyncView(APIView):
|
||||
url_prefix = ("/adt/sync",)
|
||||
|
||||
def get(self):
|
||||
if g.user.username not in ("cmdb_agent", "worker", "admin"):
|
||||
return abort(403)
|
||||
|
||||
oneagent_name = request.values.get('oneagent_name')
|
||||
oneagent_id = request.values.get('oneagent_id')
|
||||
last_update_at = request.values.get('last_update_at')
|
||||
|
||||
query = "{},oneagent_id:{}".format(oneagent_name, oneagent_id)
|
||||
current_app.logger.info(query)
|
||||
s = search(query)
|
||||
try:
|
||||
response, _, _, _, _, _ = s.search()
|
||||
except SearchError as e:
|
||||
import traceback
|
||||
current_app.logger.error(traceback.format_exc())
|
||||
return abort(400, str(e))
|
||||
|
||||
ci_id = response and response[0]["_id"]
|
||||
rules, last_update_at = AutoDiscoveryCITypeCRUD.get(ci_id, oneagent_id, last_update_at)
|
||||
|
||||
return self.jsonify(rules=rules, last_update_at=last_update_at)
|
12
cmdb-api/api/views/cmdb/c_stats.py
Normal file
12
cmdb-api/api/views/cmdb/c_stats.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
from api.lib.cmdb.cache import CMDBCounterCache
|
||||
from api.resource import APIView
|
||||
|
||||
|
||||
class CMDBStatisticsView(APIView):
|
||||
url_prefix = "/statistics"
|
||||
|
||||
def get(self):
|
||||
return self.jsonify(CMDBCounterCache.get())
|
@@ -9,14 +9,14 @@ from flask import request
|
||||
|
||||
from api.lib.cmdb.cache import CITypeCache
|
||||
from api.lib.cmdb.ci import CIManager
|
||||
from api.lib.cmdb.ci import CIRelationManager
|
||||
from api.lib.cmdb.const import ExistPolicy
|
||||
from api.lib.cmdb.const import ResourceTypeEnum, PermEnum
|
||||
from api.lib.cmdb.const import RetKey
|
||||
from api.lib.cmdb.perms import has_perm_for_ci
|
||||
from api.lib.cmdb.search import SearchError
|
||||
from api.lib.cmdb.search.ci.db.search import Search as SearchFromDB
|
||||
from api.lib.cmdb.search.ci.es.search import Search as SearchFromES
|
||||
from api.lib.cmdb.search.ci import search
|
||||
from api.lib.perm.acl.acl import has_perm_from_args
|
||||
from api.lib.perm.auth import auth_abandoned
|
||||
from api.lib.utils import get_page
|
||||
from api.lib.utils import get_page_size
|
||||
from api.lib.utils import handle_arg_list
|
||||
@@ -62,52 +62,63 @@ class CIView(APIView):
|
||||
ret_key = RetKey.NAME
|
||||
|
||||
manager = CIManager()
|
||||
ci = manager.get_ci_by_id_from_db(ci_id, ret_key=ret_key, fields=fields)
|
||||
ci = manager.get_ci_by_id_from_db(ci_id, ret_key=ret_key, fields=fields, valid=True)
|
||||
|
||||
return self.jsonify(ci_id=ci_id, ci=ci)
|
||||
|
||||
@staticmethod
|
||||
def _wrap_ci_dict():
|
||||
ci_dict = dict()
|
||||
for k, v in request.values.items():
|
||||
if k != "ci_type" and not k.startswith("_"):
|
||||
ci_dict[k] = v.strip() if isinstance(v, six.string_types) else v
|
||||
ci_dict = {k: v.strip() if isinstance(v, six.string_types) else v for k, v in request.values.items()
|
||||
if k != "ci_type" and not k.startswith("_")}
|
||||
|
||||
return ci_dict
|
||||
|
||||
@has_perm_from_args("ci_type", ResourceTypeEnum.CI, PermEnum.ADD, lambda x: CITypeCache.get(x).name)
|
||||
@has_perm_for_ci("ci_type", ResourceTypeEnum.CI, PermEnum.ADD, lambda x: CITypeCache.get(x))
|
||||
def post(self):
|
||||
ci_type = request.values.get("ci_type")
|
||||
_no_attribute_policy = request.values.get("_no_attribute_policy", ExistPolicy.IGNORE)
|
||||
_no_attribute_policy = request.values.get("no_attribute_policy", ExistPolicy.IGNORE)
|
||||
|
||||
exist_policy = request.values.pop('exist_policy', None)
|
||||
|
||||
ci_dict = self._wrap_ci_dict()
|
||||
|
||||
manager = CIManager()
|
||||
current_app.logger.debug(ci_dict)
|
||||
ci_id = manager.add(ci_type,
|
||||
exist_policy=ExistPolicy.REJECT,
|
||||
_no_attribute_policy=_no_attribute_policy, **ci_dict)
|
||||
exist_policy=exist_policy or ExistPolicy.REJECT,
|
||||
_no_attribute_policy=_no_attribute_policy,
|
||||
_is_admin=request.values.pop('__is_admin', False),
|
||||
**ci_dict)
|
||||
|
||||
return self.jsonify(ci_id=ci_id)
|
||||
|
||||
@has_perm_from_args("ci_id", ResourceTypeEnum.CI, PermEnum.UPDATE, CIManager.get_type_name)
|
||||
@has_perm_for_ci("ci_id", ResourceTypeEnum.CI, PermEnum.UPDATE, CIManager.get_type)
|
||||
def put(self, ci_id=None):
|
||||
args = request.values
|
||||
current_app.logger.info(args)
|
||||
ci_type = args.get("ci_type")
|
||||
_no_attribute_policy = args.get("_no_attribute_policy", ExistPolicy.IGNORE)
|
||||
_no_attribute_policy = args.get("no_attribute_policy", ExistPolicy.IGNORE)
|
||||
|
||||
ci_dict = self._wrap_ci_dict()
|
||||
manager = CIManager()
|
||||
if ci_id is not None:
|
||||
manager.update(ci_id, **ci_dict)
|
||||
manager.update(ci_id,
|
||||
_is_admin=request.values.pop('__is_admin', False),
|
||||
**ci_dict)
|
||||
else:
|
||||
ci_id = manager.add(ci_type,
|
||||
exist_policy=ExistPolicy.REPLACE,
|
||||
_no_attribute_policy=_no_attribute_policy,
|
||||
_is_admin=request.values.pop('__is_admin', False),
|
||||
**ci_dict)
|
||||
|
||||
return self.jsonify(ci_id=ci_id)
|
||||
|
||||
@has_perm_from_args("ci_id", ResourceTypeEnum.CI, PermEnum.DELETE, CIManager.get_type_name)
|
||||
@has_perm_for_ci("ci_id", ResourceTypeEnum.CI, PermEnum.DELETE, CIManager.get_type)
|
||||
def delete(self, ci_id):
|
||||
manager = CIManager()
|
||||
manager.delete(ci_id)
|
||||
|
||||
return self.jsonify(message="ok")
|
||||
|
||||
|
||||
@@ -116,13 +127,13 @@ class CIDetailView(APIView):
|
||||
|
||||
def get(self, ci_id):
|
||||
_ci = CI.get_by_id(ci_id).to_dict()
|
||||
|
||||
return self.jsonify(**_ci)
|
||||
|
||||
|
||||
class CISearchView(APIView):
|
||||
url_prefix = ("/ci/s", "/ci/search")
|
||||
|
||||
@auth_abandoned
|
||||
def get(self):
|
||||
"""@params: q: query statement
|
||||
fl: filter by column
|
||||
@@ -130,12 +141,12 @@ class CISearchView(APIView):
|
||||
ret_key: id, name, alias
|
||||
facet: statistic
|
||||
"""
|
||||
|
||||
page = get_page(request.values.get("page", 1))
|
||||
count = get_page_size(request.values.get("count") or request.values.get("page_size"))
|
||||
|
||||
query = request.values.get('q', "")
|
||||
fl = handle_arg_list(request.values.get('fl', ""))
|
||||
excludes = handle_arg_list(request.values.get('excludes', ""))
|
||||
ret_key = request.values.get('ret_key', RetKey.NAME)
|
||||
if ret_key not in (RetKey.NAME, RetKey.ALIAS, RetKey.ID):
|
||||
ret_key = RetKey.NAME
|
||||
@@ -143,15 +154,18 @@ class CISearchView(APIView):
|
||||
sort = request.values.get("sort")
|
||||
|
||||
start = time.time()
|
||||
if current_app.config.get("USE_ES"):
|
||||
s = SearchFromES(query, fl, facet, page, ret_key, count, sort)
|
||||
else:
|
||||
s = SearchFromDB(query, fl, facet, page, ret_key, count, sort)
|
||||
s = search(query, fl, facet, page, ret_key, count, sort, excludes)
|
||||
try:
|
||||
response, counter, total, page, numfound, facet = s.search()
|
||||
except SearchError as e:
|
||||
return abort(400, str(e))
|
||||
current_app.logger.debug("search time is :{0}".format(time.time() - start))
|
||||
|
||||
if request.values.get('need_children') in current_app.config.get('BOOL_TRUE') and len(response) == 1:
|
||||
children = CIRelationManager.get_children(response[0]['_id'], ret_key=ret_key) # one floor
|
||||
response[0].update(children)
|
||||
|
||||
current_app.logger.debug("search time is: {0}".format(time.time() - start))
|
||||
|
||||
return self.jsonify(numfound=numfound,
|
||||
total=total,
|
||||
page=page,
|
||||
@@ -159,6 +173,9 @@ class CISearchView(APIView):
|
||||
counter=counter,
|
||||
result=response)
|
||||
|
||||
def post(self):
|
||||
return self.get()
|
||||
|
||||
|
||||
class CIUnique(APIView):
|
||||
url_prefix = "/ci/<int:ci_id>/unique"
|
||||
@@ -204,7 +221,7 @@ class CIHeartbeatView(APIView):
|
||||
class CIFlushView(APIView):
|
||||
url_prefix = ("/ci/flush", "/ci/<int:ci_id>/flush")
|
||||
|
||||
@auth_abandoned
|
||||
# @auth_abandoned
|
||||
def get(self, ci_id=None):
|
||||
from api.tasks.cmdb import ci_cache
|
||||
from api.lib.cmdb.const import CMDB_QUEUE
|
||||
@@ -214,4 +231,12 @@ class CIFlushView(APIView):
|
||||
cis = CI.get_by(to_dict=False)
|
||||
for ci in cis:
|
||||
ci_cache.apply_async([ci.id], queue=CMDB_QUEUE)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class CIAutoDiscoveryStatisticsView(APIView):
|
||||
url_prefix = "/ci/adc/statistics"
|
||||
|
||||
def get(self):
|
||||
return self.jsonify(CIManager.get_ad_statistics())
|
||||
|
@@ -9,6 +9,7 @@ from flask import request
|
||||
|
||||
from api.lib.cmdb.cache import RelationTypeCache
|
||||
from api.lib.cmdb.ci import CIRelationManager
|
||||
from api.lib.cmdb.resp_format import ErrFormat
|
||||
from api.lib.cmdb.search import SearchError
|
||||
from api.lib.cmdb.search.ci_relation.search import Search
|
||||
from api.lib.decorator import args_required
|
||||
@@ -22,7 +23,6 @@ from api.resource import APIView
|
||||
class CIRelationSearchView(APIView):
|
||||
url_prefix = ("/ci_relations/s", "/ci_relations/search")
|
||||
|
||||
@auth_abandoned
|
||||
def get(self):
|
||||
"""@params: q: query statement
|
||||
fl: filter by column
|
||||
@@ -31,7 +31,6 @@ class CIRelationSearchView(APIView):
|
||||
level: default is 1
|
||||
facet: statistic
|
||||
"""
|
||||
|
||||
page = get_page(request.values.get("page", 1))
|
||||
count = get_page_size(request.values.get("count") or request.values.get("page_size"))
|
||||
|
||||
@@ -42,9 +41,10 @@ class CIRelationSearchView(APIView):
|
||||
fl = handle_arg_list(request.values.get('fl', ""))
|
||||
facet = handle_arg_list(request.values.get("facet", ""))
|
||||
sort = request.values.get("sort")
|
||||
reverse = request.values.get("reverse") in current_app.config.get('BOOL_TRUE')
|
||||
|
||||
start = time.time()
|
||||
s = Search(root_id, level, query, fl, facet, page, count, sort)
|
||||
s = Search(root_id, level, query, fl, facet, page, count, sort, reverse)
|
||||
try:
|
||||
response, counter, total, page, numfound, facet = s.search()
|
||||
except SearchError as e:
|
||||
@@ -89,7 +89,7 @@ class GetSecondCIsView(APIView):
|
||||
try:
|
||||
relation_type_id = RelationTypeCache.get(relation_type).id if relation_type else None
|
||||
except AttributeError:
|
||||
return abort(400, "invalid relation type <{0}>".format(relation_type))
|
||||
return abort(400, ErrFormat.invalid_relation_type.format(relation_type))
|
||||
|
||||
manager = CIRelationManager()
|
||||
numfound, total, second_cis = manager.get_second_cis(
|
||||
@@ -147,12 +147,12 @@ class BatchCreateOrUpdateCIRelationView(APIView):
|
||||
url_prefix = "/ci_relations/batch"
|
||||
|
||||
@args_required('ci_ids')
|
||||
@args_required('parents')
|
||||
def post(self):
|
||||
ci_ids = request.values.get('ci_ids')
|
||||
parents = request.values.get('parents')
|
||||
ci_ids = list(map(int, request.values.get('ci_ids')))
|
||||
parents = list(map(int, request.values.get('parents', [])))
|
||||
children = list(map(int, request.values.get('children', [])))
|
||||
|
||||
CIRelationManager.batch_update(ci_ids, parents)
|
||||
CIRelationManager.batch_update(ci_ids, parents, children)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
@@ -160,3 +160,13 @@ class BatchCreateOrUpdateCIRelationView(APIView):
|
||||
@args_required('parents')
|
||||
def put(self):
|
||||
return self.post()
|
||||
|
||||
@args_required('ci_ids')
|
||||
@args_required('parents')
|
||||
def delete(self):
|
||||
ci_ids = list(map(int, request.values.get('ci_ids')))
|
||||
parents = list(map(int, request.values.get('parents', [])))
|
||||
|
||||
CIRelationManager.batch_delete(ci_ids, parents)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
@@ -1,9 +1,13 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
import json
|
||||
from io import BytesIO
|
||||
|
||||
from flask import abort
|
||||
from flask import current_app
|
||||
from flask import request
|
||||
from flask import session
|
||||
|
||||
from api.lib.cmdb.cache import AttributeCache
|
||||
from api.lib.cmdb.cache import CITypeCache
|
||||
@@ -11,9 +15,23 @@ from api.lib.cmdb.ci_type import CITypeAttributeGroupManager
|
||||
from api.lib.cmdb.ci_type import CITypeAttributeManager
|
||||
from api.lib.cmdb.ci_type import CITypeGroupManager
|
||||
from api.lib.cmdb.ci_type import CITypeManager
|
||||
from api.lib.cmdb.const import RoleEnum
|
||||
from api.lib.cmdb.ci_type import CITypeTemplateManager
|
||||
from api.lib.cmdb.ci_type import CITypeTriggerManager
|
||||
from api.lib.cmdb.ci_type import CITypeUniqueConstraintManager
|
||||
from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum
|
||||
from api.lib.cmdb.perms import CIFilterPermsCRUD
|
||||
from api.lib.cmdb.preference import PreferenceManager
|
||||
from api.lib.cmdb.resp_format import ErrFormat
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.decorator import args_validate
|
||||
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 is_app_admin
|
||||
from api.lib.perm.acl.acl import role_required
|
||||
from api.lib.perm.acl.cache import AppCache
|
||||
from api.lib.perm.acl.role import RoleCRUD
|
||||
from api.lib.perm.acl.role import RoleRelationCRUD
|
||||
from api.lib.perm.auth import auth_with_app_token
|
||||
from api.lib.utils import handle_arg_list
|
||||
from api.resource import APIView
|
||||
|
||||
@@ -34,8 +52,8 @@ class CITypeView(APIView):
|
||||
|
||||
return self.jsonify(numfound=count, ci_types=ci_types)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
@args_validate(CITypeManager.cls)
|
||||
def post(self):
|
||||
params = request.values
|
||||
|
||||
@@ -49,44 +67,67 @@ class CITypeView(APIView):
|
||||
|
||||
return self.jsonify(type_id=type_id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_validate(CITypeManager.cls)
|
||||
def put(self, type_id):
|
||||
params = request.values
|
||||
|
||||
manager = CITypeManager()
|
||||
manager.update(type_id, **params)
|
||||
|
||||
return self.jsonify(type_id=type_id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
def delete(self, type_id):
|
||||
CITypeManager.delete(type_id)
|
||||
|
||||
return self.jsonify(type_id=type_id)
|
||||
|
||||
|
||||
class CITypeGroupView(APIView):
|
||||
url_prefix = ("/ci_types/groups", "/ci_types/groups/<int:gid>")
|
||||
url_prefix = ("/ci_types/groups",
|
||||
"/ci_types/groups/config",
|
||||
"/ci_types/groups/order",
|
||||
"/ci_types/groups/<int:gid>")
|
||||
|
||||
def get(self):
|
||||
config_required = True if "/config" in request.url else False
|
||||
need_other = request.values.get("need_other")
|
||||
return self.jsonify(CITypeGroupManager.get(need_other))
|
||||
|
||||
return self.jsonify(CITypeGroupManager.get(need_other, config_required))
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
@args_validate(CITypeGroupManager.cls)
|
||||
def post(self):
|
||||
name = request.values.get("name")
|
||||
group = CITypeGroupManager.add(name)
|
||||
|
||||
return self.jsonify(group.to_dict())
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def put(self, gid):
|
||||
name = request.values.get('name')
|
||||
@args_validate(CITypeGroupManager.cls)
|
||||
def put(self, gid=None):
|
||||
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')
|
||||
CITypeGroupManager.order(group_ids)
|
||||
|
||||
return self.jsonify(group_ids=group_ids)
|
||||
|
||||
name = request.values.get('name') or abort(400, ErrFormat.argument_value_required.format("name"))
|
||||
type_ids = request.values.get('type_ids')
|
||||
|
||||
CITypeGroupManager.update(gid, name, type_ids)
|
||||
|
||||
return self.jsonify(gid=gid)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def delete(self, gid):
|
||||
CITypeGroupManager.delete(gid)
|
||||
type_ids = request.values.get("type_ids")
|
||||
CITypeGroupManager.delete(gid, type_ids)
|
||||
|
||||
return self.jsonify(gid=gid)
|
||||
|
||||
|
||||
@@ -97,16 +138,18 @@ class CITypeQueryView(APIView):
|
||||
def get(self):
|
||||
q = request.args.get("q")
|
||||
res = CITypeManager.query(q)
|
||||
|
||||
return self.jsonify(ci_type=res)
|
||||
|
||||
|
||||
class EnableCITypeView(APIView):
|
||||
url_prefix = "/ci_types/<int:type_id>/enable"
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
def post(self, type_id):
|
||||
enable = request.values.get("enable", True)
|
||||
CITypeManager.set_enabled(type_id, enabled=enable)
|
||||
|
||||
return self.jsonify(type_id=type_id, enable=enable)
|
||||
|
||||
|
||||
@@ -114,16 +157,22 @@ class CITypeAttributeView(APIView):
|
||||
url_prefix = ("/ci_types/<int:type_id>/attributes", "/ci_types/<string:type_name>/attributes")
|
||||
|
||||
def get(self, type_id=None, type_name=None):
|
||||
t = CITypeCache.get(type_id) or CITypeCache.get(type_name) or abort(404, "CIType does not exist")
|
||||
t = CITypeCache.get(type_id) or CITypeCache.get(type_name) or abort(404, ErrFormat.ci_type_not_found)
|
||||
type_id = t.id
|
||||
unique_id = t.unique_id
|
||||
unique = AttributeCache.get(unique_id).name
|
||||
return self.jsonify(attributes=CITypeAttributeManager.get_attributes_by_type_id(type_id),
|
||||
|
||||
attr_filter = CIFilterPermsCRUD.get_attr_filter(type_id)
|
||||
attributes = CITypeAttributeManager.get_attributes_by_type_id(type_id)
|
||||
if attr_filter:
|
||||
attributes = [i for i in attributes if i['name'] in attr_filter]
|
||||
|
||||
return self.jsonify(attributes=attributes,
|
||||
type_id=type_id,
|
||||
unique_id=unique_id,
|
||||
unique=unique)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_required("attr_id")
|
||||
def post(self, type_id=None):
|
||||
attr_id_list = handle_arg_list(request.values.get("attr_id"))
|
||||
@@ -131,31 +180,34 @@ class CITypeAttributeView(APIView):
|
||||
params.pop("attr_id", "")
|
||||
|
||||
CITypeAttributeManager.add(type_id, attr_id_list, **params)
|
||||
|
||||
return self.jsonify(attributes=attr_id_list)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_required("attributes")
|
||||
def put(self, type_id=None):
|
||||
"""
|
||||
attributes is list, only support raw data request
|
||||
:param type_id:
|
||||
:return:
|
||||
:param type_id:
|
||||
:return:
|
||||
"""
|
||||
attributes = request.values.get("attributes")
|
||||
current_app.logger.debug(attributes)
|
||||
if not isinstance(attributes, list):
|
||||
return abort(400, "attributes must be list")
|
||||
return abort(400, ErrFormat.argument_attributes_must_be_list)
|
||||
|
||||
CITypeAttributeManager.update(type_id, attributes)
|
||||
|
||||
return self.jsonify(attributes=attributes)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_required("attr_id")
|
||||
def delete(self, type_id=None):
|
||||
"""
|
||||
Form request: attr_id is a string, separated by commas
|
||||
Raw data request: attr_id is a list
|
||||
:param type_id:
|
||||
:return:
|
||||
:param type_id:
|
||||
:return:
|
||||
"""
|
||||
attr_id_list = handle_arg_list(request.values.get("attr_id", ""))
|
||||
|
||||
@@ -164,6 +216,25 @@ class CITypeAttributeView(APIView):
|
||||
return self.jsonify(attributes=attr_id_list)
|
||||
|
||||
|
||||
class CITypesAttributeView(APIView):
|
||||
url_prefix = ("/ci_types/attributes",)
|
||||
|
||||
@args_required("type_ids", value_required=True)
|
||||
def get(self):
|
||||
type_ids = handle_arg_list(request.values.get('type_ids'))
|
||||
|
||||
attr_names = set()
|
||||
attributes = list()
|
||||
for type_id in type_ids:
|
||||
_attributes = CITypeAttributeManager.get_attributes_by_type_id(type_id)
|
||||
for _attr in _attributes:
|
||||
if _attr['name'] not in attr_names:
|
||||
attr_names.add(_attr['name'])
|
||||
attributes.append(_attr)
|
||||
|
||||
return self.jsonify(attributes=attributes)
|
||||
|
||||
|
||||
class CITypeAttributeTransferView(APIView):
|
||||
url_prefix = "/ci_types/<int:type_id>/attributes/transfer"
|
||||
|
||||
@@ -198,10 +269,18 @@ class CITypeAttributeGroupView(APIView):
|
||||
|
||||
def get(self, type_id):
|
||||
need_other = request.values.get("need_other")
|
||||
return self.jsonify(CITypeAttributeGroupManager.get_by_type_id(type_id, need_other))
|
||||
groups = CITypeAttributeGroupManager.get_by_type_id(type_id, need_other)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
attr_filter = CIFilterPermsCRUD.get_attr_filter(type_id)
|
||||
if attr_filter:
|
||||
for group in groups:
|
||||
group['attributes'] = [attr for attr in (group.get('attributes') or []) if attr['name'] in attr_filter]
|
||||
|
||||
return self.jsonify(groups)
|
||||
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_required("name")
|
||||
@args_validate(CITypeAttributeGroupManager.cls)
|
||||
def post(self, type_id):
|
||||
name = request.values.get("name").strip()
|
||||
order = request.values.get("order") or 0
|
||||
@@ -213,7 +292,9 @@ class CITypeAttributeGroupView(APIView):
|
||||
current_app.logger.warning(group.id)
|
||||
return self.jsonify(group_id=group.id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_required("name")
|
||||
@args_validate(CITypeAttributeGroupManager.cls)
|
||||
def put(self, group_id):
|
||||
name = request.values.get("name")
|
||||
order = request.values.get("order") or 0
|
||||
@@ -224,7 +305,198 @@ class CITypeAttributeGroupView(APIView):
|
||||
CITypeAttributeGroupManager.update(group_id, name, attr_order, order)
|
||||
return self.jsonify(group_id=group_id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
def delete(self, group_id):
|
||||
CITypeAttributeGroupManager.delete(group_id)
|
||||
return self.jsonify(group_id=group_id)
|
||||
|
||||
|
||||
class CITypeTemplateView(APIView):
|
||||
url_prefix = ("/ci_types/template/import", "/ci_types/template/export")
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def get(self): # export
|
||||
return self.jsonify(
|
||||
dict(ci_type_template=CITypeTemplateManager.export_template()))
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def post(self): # import
|
||||
tpt = request.values.get('ci_type_template') or {}
|
||||
|
||||
CITypeTemplateManager().import_template(tpt)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class CITypeCanDefineComputed(APIView):
|
||||
url_prefix = "/ci_types/can_define_computed"
|
||||
|
||||
@role_required(PermEnum.CONFIG)
|
||||
def get(self):
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class CITypeTemplateFileView(APIView):
|
||||
url_prefix = ("/ci_types/template/import/file", "/ci_types/template/export/file")
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def get(self): # export
|
||||
tpt_json = CITypeTemplateManager.export_template()
|
||||
tpt_json = dict(ci_type_template=tpt_json)
|
||||
|
||||
bf = BytesIO()
|
||||
bf.write(bytes(json.dumps(tpt_json).encode('utf-8')))
|
||||
bf.seek(0)
|
||||
|
||||
return self.send_file(bf,
|
||||
as_attachment=True,
|
||||
attachment_filename="cmdb_template.json",
|
||||
mimetype='application/json',
|
||||
cache_timeout=0)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def post(self): # import
|
||||
f = request.files.get('file')
|
||||
|
||||
if f is None:
|
||||
return abort(400, ErrFormat.argument_file_not_found)
|
||||
|
||||
content = f.read()
|
||||
try:
|
||||
content = json.loads(content)
|
||||
except:
|
||||
return abort(400, ErrFormat.invalid_json)
|
||||
tpt = content.get('ci_type_template')
|
||||
|
||||
CITypeTemplateManager().import_template(tpt)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class CITypeUniqueConstraintView(APIView):
|
||||
url_prefix = ("/ci_types/<int:type_id>/unique_constraint", "/ci_types/<int:type_id>/unique_constraint/<int:_id>")
|
||||
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
def get(self, type_id):
|
||||
return self.jsonify(CITypeUniqueConstraintManager.get_detail(type_id))
|
||||
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_required("attr_ids")
|
||||
def post(self, type_id):
|
||||
attr_ids = request.values.get('attr_ids')
|
||||
|
||||
return self.jsonify(CITypeUniqueConstraintManager().add(type_id, attr_ids))
|
||||
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_required("attr_ids")
|
||||
def put(self, type_id, _id):
|
||||
assert type_id is not None
|
||||
|
||||
attr_ids = request.values.get('attr_ids')
|
||||
|
||||
return self.jsonify(CITypeUniqueConstraintManager().update(_id, attr_ids))
|
||||
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
def delete(self, type_id, _id):
|
||||
assert type_id is not None
|
||||
|
||||
CITypeUniqueConstraintManager().delete(_id)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class CITypeTriggerView(APIView):
|
||||
url_prefix = ("/ci_types/<int:type_id>/triggers", "/ci_types/<int:type_id>/triggers/<int:_id>")
|
||||
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
def get(self, type_id):
|
||||
return self.jsonify(CITypeTriggerManager.get(type_id))
|
||||
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_required("attr_id")
|
||||
@args_required("notify")
|
||||
def post(self, type_id):
|
||||
attr_id = request.values.get('attr_id')
|
||||
notify = request.values.get('notify')
|
||||
|
||||
return self.jsonify(CITypeTriggerManager().add(type_id, attr_id, notify))
|
||||
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_required("notify")
|
||||
def put(self, type_id, _id):
|
||||
assert type_id is not None
|
||||
|
||||
notify = request.values.get('notify')
|
||||
|
||||
return self.jsonify(CITypeTriggerManager().update(_id, notify))
|
||||
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
def delete(self, type_id, _id):
|
||||
assert type_id is not None
|
||||
|
||||
CITypeTriggerManager().delete(_id)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class CITypeGrantView(APIView):
|
||||
url_prefix = "/ci_types/<int:type_id>/roles/<int:rid>/grant"
|
||||
|
||||
def post(self, type_id, rid):
|
||||
perms = request.values.pop('perms', None)
|
||||
|
||||
if request.values.get('attr_filter'):
|
||||
request.values['attr_filter'] = handle_arg_list(request.values.get('attr_filter', ''))
|
||||
|
||||
_type = CITypeCache.get(type_id)
|
||||
type_name = _type and _type.name or abort(404, ErrFormat.ci_type_not_found)
|
||||
acl = ACLManager('cmdb')
|
||||
if not acl.has_permission(type_name, ResourceTypeEnum.CI_TYPE, PermEnum.GRANT) and \
|
||||
not is_app_admin('cmdb'):
|
||||
return abort(403, ErrFormat.no_permission.format(type_name, PermEnum.GRANT))
|
||||
|
||||
acl.grant_resource_to_role_by_rid(type_name, rid, ResourceTypeEnum.CI_TYPE, perms)
|
||||
|
||||
CIFilterPermsCRUD().add(type_id=type_id, rid=rid, **request.values)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class CITypeRevokeView(APIView):
|
||||
url_prefix = "/ci_types/<int:type_id>/roles/<int:rid>/revoke"
|
||||
|
||||
@args_required('perms')
|
||||
def post(self, type_id, rid):
|
||||
perms = request.values.pop('perms', None)
|
||||
|
||||
if request.values.get('attr_filter'):
|
||||
request.values['attr_filter'] = handle_arg_list(request.values.get('attr_filter', ''))
|
||||
|
||||
_type = CITypeCache.get(type_id)
|
||||
type_name = _type and _type.name or abort(404, ErrFormat.ci_type_not_found)
|
||||
acl = ACLManager('cmdb')
|
||||
if not acl.has_permission(type_name, ResourceTypeEnum.CI_TYPE, PermEnum.GRANT) and \
|
||||
not is_app_admin('cmdb'):
|
||||
return abort(403, ErrFormat.no_permission.format(type_name, PermEnum.GRANT))
|
||||
|
||||
acl.revoke_resource_from_role_by_rid(type_name, rid, ResourceTypeEnum.CI_TYPE, perms)
|
||||
|
||||
if PermEnum.READ in perms:
|
||||
CIFilterPermsCRUD().delete(type_id=type_id, rid=rid)
|
||||
|
||||
app_id = AppCache.get('cmdb').id
|
||||
users = RoleRelationCRUD.get_users_by_rid(rid, app_id)
|
||||
for i in (users or []):
|
||||
if i.get('role', {}).get('id') and not RoleCRUD.has_permission(
|
||||
i.get('role').get('id'), type_name, ResourceTypeEnum.CI_TYPE, app_id, PermEnum.READ):
|
||||
PreferenceManager.delete_by_type_id(type_id, i.get('uid'))
|
||||
|
||||
return self.jsonify(type_id=type_id, rid=rid)
|
||||
|
||||
|
||||
class CITypeFilterPermissionView(APIView):
|
||||
url_prefix = "/ci_types/<int:type_id>/filters/permissions"
|
||||
|
||||
@auth_with_app_token
|
||||
def get(self, type_id):
|
||||
return self.jsonify(CIFilterPermsCRUD().get(type_id))
|
||||
|
@@ -1,11 +1,17 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
from flask import abort
|
||||
from flask import request
|
||||
|
||||
from api.lib.cmdb.ci_type import CITypeManager
|
||||
from api.lib.cmdb.ci_type import CITypeRelationManager
|
||||
from api.lib.cmdb.const import RoleEnum
|
||||
from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum
|
||||
from api.lib.cmdb.resp_format import ErrFormat
|
||||
from api.lib.decorator import args_required
|
||||
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 is_app_admin
|
||||
from api.lib.perm.acl.acl import role_required
|
||||
from api.resource import APIView
|
||||
|
||||
@@ -33,15 +39,16 @@ class CITypeRelationView(APIView):
|
||||
|
||||
return self.jsonify(res)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@has_perm_from_args("parent_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
@args_required("relation_type_id")
|
||||
def post(self, parent_id, child_id):
|
||||
relation_type_id = request.values.get("relation_type_id")
|
||||
ctr_id = CITypeRelationManager.add(parent_id, child_id, relation_type_id)
|
||||
constraint = request.values.get("constraint")
|
||||
ctr_id = CITypeRelationManager.add(parent_id, child_id, relation_type_id, constraint)
|
||||
|
||||
return self.jsonify(ctr_id=ctr_id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@has_perm_from_args("parent_id", ResourceTypeEnum.CI, PermEnum.CONFIG, CITypeManager.get_name_by_id)
|
||||
def delete(self, parent_id, child_id):
|
||||
CITypeRelationManager.delete_2(parent_id, child_id)
|
||||
|
||||
@@ -56,3 +63,42 @@ class CITypeRelationDelete2View(APIView):
|
||||
CITypeRelationManager.delete(ctr_id)
|
||||
|
||||
return self.jsonify(code=200, ctr_id=ctr_id)
|
||||
|
||||
|
||||
class CITypeRelationGrantView(APIView):
|
||||
url_prefix = "/ci_type_relations/<int:parent_id>/<int:child_id>/roles/<int:rid>/grant"
|
||||
|
||||
def post(self, parent_id, child_id, rid):
|
||||
p = CITypeManager.check_is_existed(parent_id)
|
||||
c = CITypeManager.check_is_existed(child_id)
|
||||
resource_name = CITypeRelationManager.acl_resource_name(p.name, c.name)
|
||||
|
||||
perms = request.values.get('perms')
|
||||
|
||||
acl = ACLManager('cmdb')
|
||||
if not acl.has_permission(resource_name, ResourceTypeEnum.CI_TYPE_RELATION, PermEnum.GRANT) and \
|
||||
not is_app_admin('cmdb'):
|
||||
return abort(403, ErrFormat.no_permission.format(resource_name, PermEnum.GRANT))
|
||||
|
||||
acl.grant_resource_to_role_by_rid(resource_name, rid, ResourceTypeEnum.CI_TYPE_RELATION, perms)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class CITypeRelationRevokeView(APIView):
|
||||
url_prefix = "/ci_type_relations/<int:parent_id>/<int:child_id>/roles/<int:rid>/revoke"
|
||||
|
||||
def post(self, parent_id, child_id, rid):
|
||||
p = CITypeManager.check_is_existed(parent_id)
|
||||
c = CITypeManager.check_is_existed(child_id)
|
||||
resource_name = CITypeRelationManager.acl_resource_name(p.name, c.name)
|
||||
|
||||
perms = request.values.get('perms')
|
||||
acl = ACLManager('cmdb')
|
||||
if not acl.has_permission(resource_name, ResourceTypeEnum.CI_TYPE_RELATION, PermEnum.GRANT) and \
|
||||
not is_app_admin('cmdb'):
|
||||
return abort(403, ErrFormat.no_permission.format(resource_name, PermEnum.GRANT))
|
||||
|
||||
acl.revoke_resource_from_role_by_rid(resource_name, rid, ResourceTypeEnum.CI_TYPE_RELATION, perms)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
72
cmdb-api/api/views/cmdb/custom_dashboard.py
Normal file
72
cmdb-api/api/views/cmdb/custom_dashboard.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
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 SystemConfigManager
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.decorator import args_validate
|
||||
from api.lib.perm.acl.acl import role_required
|
||||
from api.resource import APIView
|
||||
|
||||
|
||||
class CustomDashboardApiView(APIView):
|
||||
url_prefix = ("/custom_dashboard", "/custom_dashboard/<int:_id>", "/custom_dashboard/batch")
|
||||
|
||||
def get(self):
|
||||
return self.jsonify(CustomDashboardManager.get())
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_validate(CustomDashboardManager.cls)
|
||||
def post(self):
|
||||
cm = CustomDashboardManager.add(**request.values)
|
||||
|
||||
return self.jsonify(cm.to_dict())
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_validate(CustomDashboardManager.cls)
|
||||
def put(self, _id=None):
|
||||
if _id is not None:
|
||||
cm = CustomDashboardManager.update(_id, **request.values)
|
||||
|
||||
return self.jsonify(cm.to_dict())
|
||||
|
||||
CustomDashboardManager.batch_update(request.values.get("id2options"))
|
||||
|
||||
return self.jsonify(id2options=request.values.get('id2options'))
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def delete(self, _id):
|
||||
CustomDashboardManager.delete(_id)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class SystemConfigApiView(APIView):
|
||||
url_prefix = ("/system_config",)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name", value_required=True)
|
||||
def get(self):
|
||||
return self.jsonify(SystemConfigManager.get(request.values['name']))
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_validate(SystemConfigManager.cls)
|
||||
@args_required("name", value_required=True)
|
||||
@args_required("option", value_required=True)
|
||||
def post(self):
|
||||
cm = SystemConfigManager.create_or_update(**request.values)
|
||||
|
||||
return self.jsonify(cm.to_dict())
|
||||
|
||||
def put(self, _id=None):
|
||||
return self.post()
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
def delete(self):
|
||||
CustomDashboardManager.delete(request.values['name'])
|
||||
|
||||
return self.jsonify(code=200)
|
@@ -6,58 +6,92 @@ import datetime
|
||||
from flask import abort
|
||||
from flask import request
|
||||
|
||||
from api.lib.cmdb.ci import CIManager
|
||||
from api.lib.cmdb.const import ResourceTypeEnum, PermEnum
|
||||
from api.lib.cmdb.const import RoleEnum
|
||||
from api.lib.cmdb.history import AttributeHistoryManger
|
||||
from api.lib.cmdb.history import CITypeHistoryManager
|
||||
from api.lib.cmdb.resp_format import ErrFormat
|
||||
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 get_page
|
||||
from api.lib.utils import get_page_size
|
||||
from api.resource import APIView
|
||||
|
||||
|
||||
class RecordView(APIView):
|
||||
url_prefix = "/history/records"
|
||||
url_prefix = ("/history/records/attribute", "/history/records/relation")
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def get(self):
|
||||
page = get_page(request.values.get("page", 1))
|
||||
page_size = get_page_size(request.values.get("page_size"))
|
||||
_start = request.values.get("start")
|
||||
_end = request.values.get("end")
|
||||
username = request.values.get("username", "")
|
||||
operate_type = request.values.get("operate_type", "")
|
||||
type_id = request.values.get("type_id")
|
||||
start, end = None, None
|
||||
if _start:
|
||||
try:
|
||||
start = datetime.datetime.strptime(_start, '%Y-%m-%d %H:%M:%S')
|
||||
except ValueError:
|
||||
abort(400, 'incorrect start date time')
|
||||
return abort(400, ErrFormat.datetime_argument_invalid.format('start'))
|
||||
if _end:
|
||||
try:
|
||||
end = datetime.datetime.strptime(_end, '%Y-%m-%d %H:%M:%S')
|
||||
except ValueError:
|
||||
abort(400, 'incorrect end date time')
|
||||
return abort(400, ErrFormat.datetime_argument_invalid.format('start'))
|
||||
|
||||
numfound, total, res = AttributeHistoryManger.get_records(start, end, username, page, page_size)
|
||||
if "attribute" in request.url:
|
||||
total, res = AttributeHistoryManger.get_records_for_attributes(start, end, username, page, page_size,
|
||||
operate_type,
|
||||
type_id,
|
||||
request.values.get('ci_id'),
|
||||
request.values.get('attr_id'))
|
||||
return self.jsonify(records=res,
|
||||
total=total,
|
||||
**request.values)
|
||||
else:
|
||||
total, res, cis = AttributeHistoryManger.get_records_for_relation(start, end, username, page, page_size,
|
||||
operate_type,
|
||||
type_id,
|
||||
request.values.get('first_ci_id'),
|
||||
request.values.get('second_ci_id'))
|
||||
|
||||
return self.jsonify(numfound=numfound,
|
||||
records=res,
|
||||
page=page,
|
||||
total=total,
|
||||
start=_start,
|
||||
end=_end,
|
||||
username=username)
|
||||
return self.jsonify(records=res,
|
||||
total=total,
|
||||
cis=cis,
|
||||
**request.values)
|
||||
|
||||
|
||||
class CIHistoryView(APIView):
|
||||
url_prefix = "/history/ci/<int:ci_id>"
|
||||
|
||||
@has_perm_from_args("ci_id", ResourceTypeEnum.CI, PermEnum.READ, CIManager.get_type_name)
|
||||
def get(self, ci_id):
|
||||
result = AttributeHistoryManger.get_by_ci_id(ci_id)
|
||||
|
||||
return self.jsonify(result)
|
||||
|
||||
|
||||
class RecordDetailView(APIView):
|
||||
url_prefix = "/history/records/<int:record_id>"
|
||||
class CITypeHistoryView(APIView):
|
||||
url_prefix = "/history/ci_types"
|
||||
|
||||
def get(self, record_id):
|
||||
username, timestamp, attr_dict, rel_dict = AttributeHistoryManger.get_record_detail(record_id)
|
||||
return self.jsonify(username=username,
|
||||
timestamp=timestamp,
|
||||
attr_history=attr_dict,
|
||||
rel_history=rel_dict)
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def get(self):
|
||||
type_id = request.values.get("type_id")
|
||||
username = request.values.get("username")
|
||||
operate_type = request.values.get("operate_type")
|
||||
|
||||
page = get_page(request.values.get('page', 1))
|
||||
page_size = get_page_size(request.values.get('page_size', 1))
|
||||
|
||||
numfound, result = CITypeHistoryManager.get(page, page_size, username,
|
||||
type_id=type_id, operate_type=operate_type)
|
||||
|
||||
return self.jsonify(page=page,
|
||||
page_size=page_size,
|
||||
numfound=numfound,
|
||||
total=len(result),
|
||||
result=result)
|
||||
|
@@ -1,25 +1,35 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
from flask import abort
|
||||
from flask import request
|
||||
|
||||
from api.lib.cmdb.ci_type import CITypeManager
|
||||
from api.lib.cmdb.const import ResourceTypeEnum, PermEnum, RoleEnum
|
||||
from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum
|
||||
from api.lib.cmdb.perms import CIFilterPermsCRUD
|
||||
from api.lib.cmdb.preference import PreferenceManager
|
||||
from api.lib.cmdb.resp_format import ErrFormat
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.decorator import args_validate
|
||||
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 is_app_admin
|
||||
from api.lib.perm.acl.acl import role_required
|
||||
from api.lib.perm.acl.acl import validate_permission
|
||||
from api.lib.utils import handle_arg_list
|
||||
from api.resource import APIView
|
||||
|
||||
|
||||
class PreferenceShowCITypesView(APIView):
|
||||
url_prefix = "/preference/ci_types"
|
||||
url_prefix = ("/preference/ci_types", "/preference/ci_types2")
|
||||
|
||||
def get(self):
|
||||
instance = request.values.get("instance")
|
||||
tree = request.values.get("tree")
|
||||
|
||||
if "ci_types2" in request.url:
|
||||
return self.jsonify(PreferenceManager.get_types2(instance, tree))
|
||||
|
||||
return self.jsonify(PreferenceManager.get_types(instance, tree))
|
||||
|
||||
|
||||
@@ -29,14 +39,26 @@ class PreferenceShowAttributesView(APIView):
|
||||
def get(self, id_or_name):
|
||||
is_subscribed, attributes = PreferenceManager.get_show_attributes(id_or_name)
|
||||
|
||||
attr_filter = CIFilterPermsCRUD.get_attr_filter(int(id_or_name)) if str(id_or_name).isdigit() else []
|
||||
|
||||
if attr_filter:
|
||||
attributes = [i for i in attributes if i['name'] in attr_filter]
|
||||
|
||||
return self.jsonify(attributes=attributes, is_subscribed=is_subscribed)
|
||||
|
||||
@has_perm_from_args("id_or_name", ResourceTypeEnum.CI, PermEnum.READ, CITypeManager.get_name_by_id)
|
||||
@args_required("attr")
|
||||
@args_required("attr", value_required=False)
|
||||
@args_validate(PreferenceManager.pref_attr_cls)
|
||||
def post(self, id_or_name):
|
||||
id_or_name = int(id_or_name)
|
||||
attr_list = handle_arg_list(request.values.get("attr", ""))
|
||||
attr_list = handle_arg_list(request.values.get("attr", "")) # [[attr, false], ]
|
||||
orders = list(range(len(attr_list)))
|
||||
|
||||
if attr_list and not is_app_admin('cmdb'):
|
||||
resource_name = CITypeManager.get_name_by_id(id_or_name)
|
||||
if not ACLManager('cmdb').has_permission(resource_name, ResourceTypeEnum.CI, PermEnum.READ):
|
||||
from api.lib.perm.acl.resp_format import ErrFormat
|
||||
return abort(403, ErrFormat.resource_no_permission.format(resource_name, PermEnum.READ))
|
||||
|
||||
PreferenceManager.create_or_update_show_attributes(id_or_name, list(zip(attr_list, orders)))
|
||||
|
||||
return self.jsonify(type_id=id_or_name,
|
||||
@@ -53,12 +75,16 @@ class PreferenceTreeApiView(APIView):
|
||||
def get(self):
|
||||
return self.jsonify(PreferenceManager.get_tree_view())
|
||||
|
||||
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.READ, CITypeManager.get_name_by_id)
|
||||
@args_required("type_id")
|
||||
@args_required("levels")
|
||||
@args_required("levels", value_required=False)
|
||||
@args_validate(PreferenceManager.pref_tree_cls)
|
||||
def post(self):
|
||||
type_id = request.values.get("type_id")
|
||||
levels = handle_arg_list(request.values.get("levels"))
|
||||
if levels:
|
||||
if not is_app_admin("cmdb"):
|
||||
validate_permission(CITypeManager.get_name_by_id(type_id), ResourceTypeEnum.CI, PermEnum.READ)
|
||||
|
||||
res = PreferenceManager.create_or_update_tree_view(type_id, levels)
|
||||
|
||||
return self.jsonify(res and res.to_dict() or {})
|
||||
@@ -78,6 +104,7 @@ class PreferenceRelationApiView(APIView):
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
@args_required("cr_ids")
|
||||
@args_validate(PreferenceManager.pref_rel_cls)
|
||||
def post(self):
|
||||
name = request.values.get("name")
|
||||
cr_ids = request.values.get("cr_ids")
|
||||
@@ -96,3 +123,65 @@ class PreferenceRelationApiView(APIView):
|
||||
PreferenceManager.delete_relation_view(name)
|
||||
|
||||
return self.jsonify(name=name)
|
||||
|
||||
|
||||
class PreferenceSearchOptionView(APIView):
|
||||
url_prefix = ("/preference/search/option", "/preference/search/option/<int:_id>")
|
||||
|
||||
def get(self):
|
||||
res = PreferenceManager.get_search_option(**request.values)
|
||||
|
||||
return self.jsonify(res)
|
||||
|
||||
@args_required("name", value_required=True)
|
||||
@args_required("option", value_required=True)
|
||||
@args_validate(PreferenceManager.pre_so_cls)
|
||||
def post(self):
|
||||
res = PreferenceManager.add_search_option(**request.values)
|
||||
|
||||
return self.jsonify(res.to_dict())
|
||||
|
||||
@args_validate(PreferenceManager.pre_so_cls)
|
||||
def put(self, _id):
|
||||
res = PreferenceManager.update_search_option(_id, **request.values)
|
||||
|
||||
return self.jsonify(res.to_dict())
|
||||
|
||||
def delete(self, _id):
|
||||
PreferenceManager.delete_search_option(_id)
|
||||
|
||||
return self.jsonify(id=_id)
|
||||
|
||||
|
||||
class PreferenceRelationGrantView(APIView):
|
||||
url_prefix = "/preference/relation/view/roles/<int:rid>/grant"
|
||||
|
||||
def post(self, rid):
|
||||
name = request.values.get("name")
|
||||
perms = request.values.get('perms')
|
||||
|
||||
acl = ACLManager('cmdb')
|
||||
if not acl.has_permission(name, ResourceTypeEnum.RELATION_VIEW, PermEnum.GRANT) and \
|
||||
not is_app_admin('cmdb'):
|
||||
return abort(403, ErrFormat.no_permission.format(name, PermEnum.GRANT))
|
||||
|
||||
acl.grant_resource_to_role_by_rid(name, rid, ResourceTypeEnum.RELATION_VIEW, perms)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
||||
|
||||
class PreferenceRelationRevokeView(APIView):
|
||||
url_prefix = "/preference/relation/view/roles/<int:rid>/revoke"
|
||||
|
||||
def post(self, rid):
|
||||
name = request.values.get("name")
|
||||
perms = request.values.get('perms')
|
||||
|
||||
acl = ACLManager('cmdb')
|
||||
if not acl.has_permission(name, ResourceTypeEnum.RELATION_VIEW, PermEnum.GRANT) and \
|
||||
not is_app_admin('cmdb'):
|
||||
return abort(403, ErrFormat.no_permission.format(name, PermEnum.GRANT))
|
||||
|
||||
acl.revoke_resource_from_role_by_rid(name, rid, ResourceTypeEnum.RELATION_VIEW, perms)
|
||||
|
||||
return self.jsonify(code=200)
|
||||
|
@@ -6,7 +6,9 @@ from flask import request
|
||||
|
||||
from api.lib.cmdb.const import RoleEnum
|
||||
from api.lib.cmdb.relation_type import RelationTypeManager
|
||||
from api.lib.cmdb.resp_format import ErrFormat
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.decorator import args_validate
|
||||
from api.lib.perm.acl.acl import role_required
|
||||
from api.resource import APIView
|
||||
|
||||
@@ -19,19 +21,24 @@ class RelationTypeView(APIView):
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
@args_validate(RelationTypeManager.cls)
|
||||
def post(self):
|
||||
name = request.values.get("name") or abort(400, "Name cannot be empty")
|
||||
name = request.values.get("name") or abort(400, ErrFormat.argument_value_required.format("name"))
|
||||
rel = RelationTypeManager.add(name)
|
||||
|
||||
return self.jsonify(rel.to_dict())
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
@args_validate(RelationTypeManager.cls)
|
||||
def put(self, rel_id):
|
||||
name = request.values.get("name") or abort(400, "Name cannot be empty")
|
||||
name = request.values.get("name") or abort(400, ErrFormat.argument_value_required.format("name"))
|
||||
rel = RelationTypeManager.update(rel_id, name)
|
||||
|
||||
return self.jsonify(rel.to_dict())
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def delete(self, rel_id):
|
||||
RelationTypeManager.delete(rel_id)
|
||||
|
||||
return self.jsonify(rel_id=rel_id)
|
||||
|
Reference in New Issue
Block a user