前后端全面升级

This commit is contained in:
pycook
2023-07-10 17:42:15 +08:00
parent c444fed436
commit db5ff60aff
629 changed files with 97789 additions and 23995 deletions

View File

@@ -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))

View 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)

View 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())

View File

@@ -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())

View File

@@ -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)

View File

@@ -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))

View File

@@ -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)

View 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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)