mirror of
https://github.com/veops/cmdb.git
synced 2025-08-07 12:40:13 +08:00
升级后端并开源UI
This commit is contained in:
31
api/views/__init__.py
Normal file
31
api/views/__init__.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
import os
|
||||
|
||||
from flask import Blueprint
|
||||
from flask_restful import Api
|
||||
|
||||
from api.resource import register_resources
|
||||
from .permission import GetResourcesView, HasPermissionView, GetUserInfoView
|
||||
from .account import LoginView, LogoutView
|
||||
|
||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
# account
|
||||
blueprint_account = Blueprint('account_api', __name__, url_prefix='/api')
|
||||
account_rest = Api(blueprint_account)
|
||||
account_rest.add_resource(LoginView, LoginView.url_prefix)
|
||||
account_rest.add_resource(LogoutView, LogoutView.url_prefix)
|
||||
|
||||
# permission
|
||||
blueprint_perm_v01 = Blueprint('permission_api', __name__, url_prefix='/api/v1/perms')
|
||||
perm_rest = Api(blueprint_perm_v01)
|
||||
perm_rest.add_resource(GetResourcesView, GetResourcesView.url_prefix)
|
||||
perm_rest.add_resource(HasPermissionView, HasPermissionView.url_prefix)
|
||||
perm_rest.add_resource(GetUserInfoView, GetUserInfoView.url_prefix)
|
||||
|
||||
|
||||
# cmdb
|
||||
blueprint_cmdb_v01 = Blueprint('cmdb_api_v01', __name__, url_prefix='/api/v0.1')
|
||||
rest = Api(blueprint_cmdb_v01)
|
||||
register_resources(os.path.join(HERE, "cmdb"), rest)
|
47
api/views/account.py
Normal file
47
api/views/account.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
import datetime
|
||||
|
||||
import jwt
|
||||
from flask import request
|
||||
from flask import current_app
|
||||
from flask import abort
|
||||
from flask_login import login_user, logout_user
|
||||
|
||||
from api.resource import APIView
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.perm.auth import auth_abandoned
|
||||
from api.models.account import User
|
||||
|
||||
|
||||
class LoginView(APIView):
|
||||
url_prefix = "/login"
|
||||
|
||||
@args_required("username")
|
||||
@args_required("password")
|
||||
@auth_abandoned
|
||||
def post(self):
|
||||
username = request.values.get("username") or request.values.get("email")
|
||||
password = request.values.get("password")
|
||||
user, authenticated = User.query.authenticate(username, password)
|
||||
if not authenticated:
|
||||
return abort(401, "invalid username or password")
|
||||
|
||||
login_user(user)
|
||||
|
||||
token = jwt.encode({
|
||||
'sub': user.email,
|
||||
'iat': datetime.datetime.now(),
|
||||
'exp': datetime.datetime.now() + datetime.timedelta(minutes=24 * 60 * 7)},
|
||||
current_app.config['SECRET_KEY'])
|
||||
|
||||
return self.jsonify(token=token.decode())
|
||||
|
||||
|
||||
class LogoutView(APIView):
|
||||
url_prefix = "/logout"
|
||||
|
||||
@auth_abandoned
|
||||
def post(self):
|
||||
logout_user()
|
||||
self.jsonify(code=200)
|
1
api/views/cmdb/__init__.py
Normal file
1
api/views/cmdb/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# -*- coding:utf-8 -*-
|
65
api/views/cmdb/attribute.py
Normal file
65
api/views/cmdb/attribute.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
from flask import request
|
||||
from flask import abort
|
||||
from flask import current_app
|
||||
|
||||
from api.resource import APIView
|
||||
from api.lib.perm.acl import role_required
|
||||
from api.lib.cmdb.const import RoleEnum
|
||||
from api.lib.cmdb.attribute import AttributeManager
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.utils import handle_arg_list
|
||||
|
||||
|
||||
class AttributeSearchView(APIView):
|
||||
url_prefix = ("/attributes/s", "/attributes/search")
|
||||
|
||||
def get(self):
|
||||
q = request.values.get("q")
|
||||
attrs = AttributeManager().get_attributes(name=q)
|
||||
count = len(attrs)
|
||||
return self.jsonify(numfound=count, attributes=attrs)
|
||||
|
||||
|
||||
class AttributeView(APIView):
|
||||
url_prefix = ("/attributes", "/attributes/<string:attr_name>", "/attributes/<int:attr_id>")
|
||||
|
||||
def get(self, attr_name=None, attr_id=None):
|
||||
attr_manager = AttributeManager()
|
||||
attr_dict = None
|
||||
if attr_name is not None:
|
||||
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)
|
||||
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)
|
||||
@args_required("name")
|
||||
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)
|
||||
def put(self, attr_id):
|
||||
choice_value = handle_arg_list(request.values.get("choice_value"))
|
||||
params = request.values
|
||||
params["choice_value"] = choice_value
|
||||
current_app.logger.debug(params)
|
||||
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))
|
218
api/views/cmdb/ci.py
Normal file
218
api/views/cmdb/ci.py
Normal file
@@ -0,0 +1,218 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
import time
|
||||
|
||||
import six
|
||||
from flask import abort
|
||||
from flask import current_app
|
||||
from flask import request
|
||||
|
||||
from api.lib.perm.acl import has_perm_from_args
|
||||
from api.lib.cmdb.const import ResourceType, PermEnum
|
||||
from api.lib.cmdb.cache import CITypeCache
|
||||
from api.lib.cmdb.ci import CIManager
|
||||
from api.lib.cmdb.const import ExistPolicy
|
||||
from api.lib.cmdb.const import RetKey
|
||||
from api.lib.cmdb.search import Search
|
||||
from api.lib.cmdb.search import SearchError
|
||||
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
|
||||
from api.models.cmdb import CI
|
||||
from api.resource import APIView
|
||||
|
||||
|
||||
class CIsByTypeView(APIView):
|
||||
url_prefix = "/ci/type/<int:type_id>"
|
||||
|
||||
def get(self, type_id):
|
||||
fields = handle_arg_list(request.values.get("fields", ""))
|
||||
|
||||
ret_key = request.values.get("ret_key", RetKey.NAME)
|
||||
if ret_key not in (RetKey.NAME, RetKey.ALIAS, RetKey.ID):
|
||||
ret_key = RetKey.NAME
|
||||
|
||||
page = get_page(request.values.get("page", 1))
|
||||
count = get_page_size(request.values.get("count"))
|
||||
|
||||
manager = CIManager()
|
||||
res = manager.get_cis_by_type(type_id,
|
||||
ret_key=ret_key,
|
||||
fields=fields,
|
||||
page=page,
|
||||
per_page=count)
|
||||
|
||||
return self.jsonify(type_id=type_id,
|
||||
numfound=res[0],
|
||||
total=len(res[2]),
|
||||
page=res[1],
|
||||
cis=res[2])
|
||||
|
||||
|
||||
class CIView(APIView):
|
||||
url_prefix = ("/ci/<int:ci_id>", "/ci")
|
||||
|
||||
def get(self, ci_id):
|
||||
fields = handle_arg_list(request.values.get("fields", ""))
|
||||
|
||||
ret_key = request.values.get("ret_key", RetKey.NAME)
|
||||
if ret_key not in (RetKey.NAME, RetKey.ALIAS, RetKey.ID):
|
||||
ret_key = RetKey.NAME
|
||||
|
||||
manager = CIManager()
|
||||
ci = manager.get_ci_by_id_from_db(ci_id, ret_key=ret_key, fields=fields)
|
||||
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
|
||||
return ci_dict
|
||||
|
||||
@has_perm_from_args("ci_type", ResourceType.CI, PermEnum.ADD)
|
||||
def post(self):
|
||||
ci_type = request.values.get("ci_type")
|
||||
_no_attribute_policy = request.values.get("_no_attribute_policy", ExistPolicy.IGNORE)
|
||||
|
||||
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)
|
||||
return self.jsonify(ci_id=ci_id)
|
||||
|
||||
@has_perm_from_args("ci_id", ResourceType.CI, PermEnum.UPDATE, CIManager.get_type_name)
|
||||
def put(self, ci_id=None):
|
||||
args = request.values
|
||||
ci_type = args.get("ci_type")
|
||||
_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)
|
||||
else:
|
||||
ci_id = manager.add(ci_type,
|
||||
exist_policy=ExistPolicy.REPLACE,
|
||||
_no_attribute_policy=_no_attribute_policy,
|
||||
**ci_dict)
|
||||
return self.jsonify(ci_id=ci_id)
|
||||
|
||||
@has_perm_from_args("ci_id", ResourceType.CI, PermEnum.DELETE, CIManager.get_type_name)
|
||||
def delete(self, ci_id):
|
||||
manager = CIManager()
|
||||
manager.delete(ci_id)
|
||||
return self.jsonify(message="ok")
|
||||
|
||||
|
||||
class CIDetailView(APIView):
|
||||
url_prefix = "/ci/<int:ci_id>/detail"
|
||||
|
||||
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
|
||||
count: the number of ci
|
||||
ret_key: id, name, alias
|
||||
facet: statistic
|
||||
"""
|
||||
|
||||
page = get_page(request.values.get("page", 1))
|
||||
count = get_page_size(request.values.get("count"))
|
||||
|
||||
query = request.values.get('q', "")
|
||||
fl = handle_arg_list(request.values.get('fl', ""))
|
||||
ret_key = request.values.get('ret_key', RetKey.NAME)
|
||||
if ret_key not in (RetKey.NAME, RetKey.ALIAS, RetKey.ID):
|
||||
ret_key = RetKey.NAME
|
||||
facet = handle_arg_list(request.values.get("facet", ""))
|
||||
fl = list(filter(lambda x: x != "", fl))
|
||||
facet = list(filter(lambda x: x != "", facet))
|
||||
sort = request.values.get("sort")
|
||||
|
||||
start = time.time()
|
||||
s = Search(query, fl, facet, page, ret_key, count, sort)
|
||||
try:
|
||||
response, counter, total, page, numfound, facet = s.search()
|
||||
except SearchError as e:
|
||||
return abort(400, str(e))
|
||||
except Exception as e:
|
||||
current_app.logger.error(str(e))
|
||||
return abort(500, "search unknown error")
|
||||
current_app.logger.debug("search time is :{0}".format(time.time() - start))
|
||||
return self.jsonify(numfound=numfound,
|
||||
total=total,
|
||||
page=page,
|
||||
facet=facet,
|
||||
counter=counter,
|
||||
result=response)
|
||||
|
||||
|
||||
class CIUnique(APIView):
|
||||
url_prefix = "/ci/<int:ci_id>/unique"
|
||||
|
||||
@has_perm_from_args("ci_id", ResourceType.CI, PermEnum.UPDATE, CIManager.get_type_name)
|
||||
def put(self, ci_id):
|
||||
params = request.values
|
||||
unique_name = params.keys()[0]
|
||||
unique_value = params.values()[0]
|
||||
|
||||
CIManager.update_unique_value(ci_id, unique_name, unique_value)
|
||||
|
||||
return self.jsonify(ci_id=ci_id)
|
||||
|
||||
|
||||
class CIHeartbeatView(APIView):
|
||||
url_prefix = ("/ci/heartbeat", "/ci/heartbeat/<string:ci_type>/<string:unique>")
|
||||
|
||||
def get(self):
|
||||
page = get_page(request.values.get("page", 1))
|
||||
ci_type = request.values.get("ci_type", "").strip()
|
||||
try:
|
||||
type_id = CITypeCache.get(ci_type).type_id
|
||||
except AttributeError:
|
||||
return self.jsonify(numfound=0, result=[])
|
||||
agent_status = request.values.get("agent_status")
|
||||
if agent_status:
|
||||
agent_status = int(agent_status)
|
||||
|
||||
numfound, result = CIManager.get_heartbeat(page, type_id, agent_status=agent_status)
|
||||
|
||||
return self.jsonify(numfound=numfound, result=result)
|
||||
|
||||
def post(self, ci_type, unique):
|
||||
if not unique or not ci_type:
|
||||
return self.jsonify(message="error")
|
||||
|
||||
msg, cmd = CIManager().add_heartbeat(ci_type, unique)
|
||||
|
||||
return self.jsonify(message=msg, cmd=cmd)
|
||||
|
||||
|
||||
class CIFlushView(APIView):
|
||||
url_prefix = ("/ci/flush", "/ci/<int:ci_id>/flush")
|
||||
|
||||
@auth_abandoned
|
||||
def get(self, ci_id=None):
|
||||
from api.tasks.cmdb import ci_cache
|
||||
from api.lib.cmdb.const import CMDB_QUEUE
|
||||
if ci_id is not None:
|
||||
ci_cache.apply_async([ci_id], queue=CMDB_QUEUE)
|
||||
else:
|
||||
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)
|
66
api/views/cmdb/ci_relation.py
Normal file
66
api/views/cmdb/ci_relation.py
Normal file
@@ -0,0 +1,66 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
from flask import request
|
||||
|
||||
from api.lib.cmdb.ci import CIRelationManager
|
||||
from api.lib.utils import get_page
|
||||
from api.lib.utils import get_page_size
|
||||
from api.resource import APIView
|
||||
|
||||
|
||||
class GetSecondCIsView(APIView):
|
||||
url_prefix = "/ci_relations/<int:first_ci_id>/second_cis"
|
||||
|
||||
def get(self, first_ci_id):
|
||||
page = get_page(request.values.get("page", 1))
|
||||
count = get_page_size(request.values.get("count"))
|
||||
relation_type = request.values.get("relation_type", "contain")
|
||||
|
||||
manager = CIRelationManager()
|
||||
numfound, total, second_cis = manager.get_second_cis(
|
||||
first_ci_id, page=page, per_page=count, relation_type=relation_type)
|
||||
|
||||
return self.jsonify(numfound=numfound,
|
||||
total=total,
|
||||
page=page,
|
||||
second_cis=second_cis)
|
||||
|
||||
|
||||
class GetFirstCIsView(APIView):
|
||||
url_prefix = "/ci_relations/<int:second_ci_id>/first_cis"
|
||||
|
||||
def get(self, second_ci_id):
|
||||
page = get_page(request.values.get("page", 1))
|
||||
count = get_page_size(request.values.get("count"))
|
||||
|
||||
manager = CIRelationManager()
|
||||
numfound, total, first_cis = manager.get_first_cis(second_ci_id, per_page=count, page=page)
|
||||
|
||||
return self.jsonify(numfound=numfound,
|
||||
total=total,
|
||||
page=page,
|
||||
first_cis=first_cis)
|
||||
|
||||
|
||||
class CIRelationView(APIView):
|
||||
url_prefix = "/ci_relations/<int:first_ci_id>/<int:second_ci_id>"
|
||||
|
||||
def post(self, first_ci_id, second_ci_id):
|
||||
manager = CIRelationManager()
|
||||
res = manager.add(first_ci_id, second_ci_id)
|
||||
return self.jsonify(cr_id=res)
|
||||
|
||||
def delete(self, first_ci_id, second_ci_id):
|
||||
manager = CIRelationManager()
|
||||
manager.delete_2(first_ci_id, second_ci_id)
|
||||
return self.jsonify(message="CIType Relation is deleted")
|
||||
|
||||
|
||||
class DeleteCIRelationView(APIView):
|
||||
url_prefix = "/ci_relations/<int:cr_id>"
|
||||
|
||||
def delete(self, cr_id):
|
||||
manager = CIRelationManager()
|
||||
manager.delete(cr_id)
|
||||
return self.jsonify(message="CIType Relation is deleted")
|
202
api/views/cmdb/ci_type.py
Normal file
202
api/views/cmdb/ci_type.py
Normal file
@@ -0,0 +1,202 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
from flask import abort
|
||||
from flask import current_app
|
||||
from flask import request
|
||||
|
||||
from api.resource import APIView
|
||||
from api.lib.perm.acl import role_required
|
||||
from api.lib.cmdb.const import RoleEnum
|
||||
from api.lib.cmdb.cache import AttributeCache
|
||||
from api.lib.cmdb.cache import CITypeCache
|
||||
from api.lib.cmdb.ci_type import CITypeAttributeManager
|
||||
from api.lib.cmdb.ci_type import CITypeManager
|
||||
from api.lib.cmdb.ci_type import CITypeGroupManager
|
||||
from api.lib.cmdb.ci_type import CITypeAttributeGroupManager
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.utils import handle_arg_list
|
||||
|
||||
|
||||
class CITypeView(APIView):
|
||||
url_prefix = ("/ci_types", "/ci_types/<int:type_id>", "/ci_types/<string:type_name>")
|
||||
|
||||
def get(self, type_id=None, type_name=None):
|
||||
q = request.args.get("type_name")
|
||||
|
||||
if type_id is not None:
|
||||
ci_types = [CITypeCache.get(type_id).to_dict()]
|
||||
elif type_name is not None:
|
||||
ci_types = [CITypeCache.get(type_name).to_dict()]
|
||||
else:
|
||||
ci_types = CITypeManager().get_ci_types(q)
|
||||
count = len(ci_types)
|
||||
|
||||
return self.jsonify(numfound=count, ci_types=ci_types)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
def post(self):
|
||||
params = request.values
|
||||
|
||||
type_name = params.get("name")
|
||||
type_alias = params.get("alias")
|
||||
type_alias = type_name if not type_alias else type_alias
|
||||
params['alias'] = type_alias
|
||||
|
||||
manager = CITypeManager()
|
||||
type_id = manager.add(**params)
|
||||
|
||||
return self.jsonify(type_id=type_id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
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)
|
||||
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>")
|
||||
|
||||
def get(self):
|
||||
need_other = request.values.get("need_other")
|
||||
return self.jsonify(CITypeGroupManager.get(need_other))
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
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')
|
||||
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)
|
||||
return self.jsonify(gid=gid)
|
||||
|
||||
|
||||
class CITypeQueryView(APIView):
|
||||
url_prefix = "/ci_types/query"
|
||||
|
||||
@args_required("q")
|
||||
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)
|
||||
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)
|
||||
|
||||
|
||||
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")
|
||||
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),
|
||||
type_id=type_id,
|
||||
unique_id=unique_id,
|
||||
unique=unique)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("attr_id")
|
||||
def post(self, type_id=None):
|
||||
attr_id_list = handle_arg_list(request.values.get("attr_id"))
|
||||
params = request.values
|
||||
params.pop("attr_id", "")
|
||||
|
||||
CITypeAttributeManager.add(type_id, attr_id_list, **params)
|
||||
return self.jsonify(attributes=attr_id_list)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("attributes")
|
||||
def put(self, type_id=None):
|
||||
"""
|
||||
attributes is list, only support raw data request
|
||||
: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")
|
||||
CITypeAttributeManager.update(type_id, attributes)
|
||||
return self.jsonify(attributes=attributes)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@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:
|
||||
"""
|
||||
attr_id_list = handle_arg_list(request.values.get("attr_id", ""))
|
||||
|
||||
CITypeAttributeManager.delete(type_id, attr_id_list)
|
||||
|
||||
return self.jsonify(attributes=attr_id_list)
|
||||
|
||||
|
||||
class CITypeAttributeGroupView(APIView):
|
||||
url_prefix = ("/ci_types/<int:type_id>/attribute_groups",
|
||||
"/ci_types/attribute_groups/<int:group_id>")
|
||||
|
||||
def get(self, type_id):
|
||||
need_other = request.values.get("need_other")
|
||||
return self.jsonify(CITypeAttributeGroupManager.get_by_type_id(type_id, need_other))
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
def post(self, type_id):
|
||||
name = request.values.get("name").strip()
|
||||
order = request.values.get("order") or 0
|
||||
attrs = handle_arg_list(request.values.get("attributes", ""))
|
||||
orders = list(range(len(attrs)))
|
||||
|
||||
attr_order = list(zip(attrs, orders))
|
||||
group = CITypeAttributeGroupManager.create_or_update(type_id, name, attr_order, order)
|
||||
current_app.logger.warning(group.id)
|
||||
return self.jsonify(group_id=group.id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def put(self, group_id):
|
||||
name = request.values.get("name")
|
||||
order = request.values.get("order") or 0
|
||||
attrs = handle_arg_list(request.values.get("attributes", ""))
|
||||
orders = list(range(len(attrs)))
|
||||
|
||||
attr_order = list(zip(attrs, orders))
|
||||
CITypeAttributeGroupManager.update(group_id, name, attr_order, order)
|
||||
return self.jsonify(group_id=group_id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def delete(self, group_id):
|
||||
CITypeAttributeGroupManager.delete(group_id)
|
||||
return self.jsonify(group_id=group_id)
|
49
api/views/cmdb/ci_type_relation.py
Normal file
49
api/views/cmdb/ci_type_relation.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
from flask import request
|
||||
|
||||
from api.lib.perm.acl import role_required
|
||||
from api.lib.cmdb.const import RoleEnum
|
||||
from api.lib.cmdb.ci_type import CITypeRelationManager
|
||||
from api.lib.decorator import args_required
|
||||
from api.resource import APIView
|
||||
|
||||
|
||||
class GetChildrenView(APIView):
|
||||
url_prefix = "/ci_type_relations/<int:parent_id>/children"
|
||||
|
||||
def get(self, parent_id):
|
||||
return self.jsonify(children=CITypeRelationManager.get_children(parent_id))
|
||||
|
||||
|
||||
class GetParentsView(APIView):
|
||||
url_prefix = "/ci_type_relations/<int:child_id>/parents"
|
||||
|
||||
def get(self, child_id):
|
||||
return self.jsonify(parents=CITypeRelationManager.get_parents(child_id))
|
||||
|
||||
|
||||
class CITypeRelationView(APIView):
|
||||
url_prefix = "/ci_type_relations/<int:parent_id>/<int:child_id>"
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@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)
|
||||
return self.jsonify(ctr_id=ctr_id)
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def delete(self, parent_id, child_id):
|
||||
CITypeRelationManager.delete_2(parent_id, child_id)
|
||||
return self.jsonify(code=200, parent_id=parent_id, child_id=child_id)
|
||||
|
||||
|
||||
class CITypeRelationDelete2View(APIView):
|
||||
url_prefix = "/ci_type_relations/<int:ctr_id>"
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
def delete(self, ctr_id):
|
||||
CITypeRelationManager.delete(ctr_id)
|
||||
return self.jsonify(code=200, ctr_id=ctr_id)
|
63
api/views/cmdb/history.py
Normal file
63
api/views/cmdb/history.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
import datetime
|
||||
|
||||
from flask import abort
|
||||
from flask import request
|
||||
|
||||
from api.lib.cmdb.history import AttributeHistoryManger
|
||||
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"
|
||||
|
||||
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", "")
|
||||
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')
|
||||
if _end:
|
||||
try:
|
||||
end = datetime.datetime.strptime(_end, '%Y-%m-%d %H:%M:%S')
|
||||
except ValueError:
|
||||
abort(400, 'incorrect end date time')
|
||||
|
||||
numfound, total, res = AttributeHistoryManger.get_records(start, end, username, page, page_size)
|
||||
|
||||
return self.jsonify(numfound=numfound,
|
||||
records=res,
|
||||
page=page,
|
||||
total=total,
|
||||
start=_start,
|
||||
end=_end,
|
||||
username=username)
|
||||
|
||||
|
||||
class CIHistoryView(APIView):
|
||||
url_prefix = "/history/ci/<int:ci_id>"
|
||||
|
||||
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>"
|
||||
|
||||
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)
|
89
api/views/cmdb/preference.py
Normal file
89
api/views/cmdb/preference.py
Normal file
@@ -0,0 +1,89 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
from flask import request
|
||||
|
||||
from api.resource import APIView
|
||||
from api.lib.perm.acl import has_perm_from_args
|
||||
from api.lib.cmdb.const import ResourceType, PermEnum
|
||||
from api.lib.cmdb.preference import PreferenceManager
|
||||
from api.lib.cmdb.ci import CIManager
|
||||
from api.lib.cmdb.ci_type import CITypeManager
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.utils import handle_arg_list
|
||||
|
||||
|
||||
class PreferenceShowCITypesView(APIView):
|
||||
url_prefix = "/preference/ci_types"
|
||||
|
||||
def get(self):
|
||||
instance = request.values.get("instance")
|
||||
tree = request.values.get("tree")
|
||||
return self.jsonify(PreferenceManager.get_types(instance, tree))
|
||||
|
||||
|
||||
class PreferenceShowAttributesView(APIView):
|
||||
url_prefix = "/preference/ci_types/<id_or_name>/attributes"
|
||||
|
||||
def get(self, id_or_name):
|
||||
is_subscribed, attributes = PreferenceManager.get_show_attributes(id_or_name)
|
||||
return self.jsonify(attributes=attributes, is_subscribed=is_subscribed)
|
||||
|
||||
@has_perm_from_args("id_or_name", ResourceType.CI, PermEnum.READ, CITypeManager.get_name_by_id)
|
||||
@args_required("attr")
|
||||
def post(self, id_or_name):
|
||||
id_or_name = int(id_or_name)
|
||||
attr_list = handle_arg_list(request.values.get("attr", ""))
|
||||
orders = list(range(len(attr_list)))
|
||||
PreferenceManager.create_or_update_show_attributes(id_or_name, list(zip(attr_list, orders)))
|
||||
return self.jsonify(type_id=id_or_name,
|
||||
attr_order=list(zip(attr_list, orders)))
|
||||
|
||||
@has_perm_from_args("id_or_name", ResourceType.CI, PermEnum.READ, CITypeManager.get_name_by_id)
|
||||
def put(self, id_or_name):
|
||||
self.post(id_or_name)
|
||||
|
||||
|
||||
class PreferenceTreeApiView(APIView):
|
||||
url_prefix = "/preference/tree/view"
|
||||
|
||||
def get(self):
|
||||
return self.jsonify(PreferenceManager.get_tree_view())
|
||||
|
||||
@has_perm_from_args("type_id", ResourceType.CI, PermEnum.READ, CITypeManager.get_name_by_id)
|
||||
@args_required("type_id")
|
||||
@args_required("levels")
|
||||
def post(self):
|
||||
type_id = request.values.get("type_id")
|
||||
levels = handle_arg_list(request.values.get("levels"))
|
||||
res = PreferenceManager.create_or_update_tree_view(type_id, levels)
|
||||
return self.jsonify(res and res.to_dict() or {})
|
||||
|
||||
def put(self):
|
||||
self.post()
|
||||
|
||||
|
||||
class PreferenceRelationApiView(APIView):
|
||||
url_prefix = "/preference/relation/view"
|
||||
|
||||
def get(self):
|
||||
return self.jsonify(PreferenceManager.get_relation_view())
|
||||
|
||||
@has_perm_from_args("parent_id", ResourceType.CI, PermEnum.READ, CITypeManager.get_name_by_id)
|
||||
@has_perm_from_args("child_id", ResourceType.CI, PermEnum.READ, CITypeManager.get_name_by_id)
|
||||
@args_required("name")
|
||||
def post(self):
|
||||
name = request.values.get("name")
|
||||
parent_id = request.values.get("parent_id")
|
||||
child_id = request.values.get("child_id")
|
||||
res = PreferenceManager.create_or_update_relation_view(name, parent_id, child_id)
|
||||
return self.jsonify(res.to_dict())
|
||||
|
||||
def put(self):
|
||||
self.post()
|
||||
|
||||
@args_required("name")
|
||||
def delete(self):
|
||||
name = request.values.get("name")
|
||||
PreferenceManager.delete_relation_view(name)
|
||||
return self.jsonify(name=name)
|
37
api/views/cmdb/relation_type.py
Normal file
37
api/views/cmdb/relation_type.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
|
||||
from flask import request
|
||||
from flask import abort
|
||||
|
||||
from api.resource import APIView
|
||||
from api.lib.perm.acl import role_required
|
||||
from api.lib.cmdb.const import RoleEnum
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.cmdb.relation_type import RelationTypeManager
|
||||
|
||||
|
||||
class RelationTypeView(APIView):
|
||||
url_prefix = ("/relation_types", "/relation_types/<int:rel_id>")
|
||||
|
||||
def get(self):
|
||||
return self.jsonify([i.to_dict() for i in RelationTypeManager.get_all()])
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
def post(self):
|
||||
name = request.values.get("name") or abort(400, "Name cannot be empty")
|
||||
rel = RelationTypeManager.add(name)
|
||||
return self.jsonify(rel.to_dict())
|
||||
|
||||
@role_required(RoleEnum.CONFIG)
|
||||
@args_required("name")
|
||||
def put(self, rel_id):
|
||||
name = request.values.get("name") or abort(400, "Name cannot be empty")
|
||||
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)
|
49
api/views/permission.py
Normal file
49
api/views/permission.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
from flask import request
|
||||
from flask import session
|
||||
from flask_login import current_user
|
||||
|
||||
from api.lib.decorator import args_required
|
||||
from api.lib.perm.acl import ACLManager
|
||||
from api.lib.perm.acl import validate_permission
|
||||
from api.resource import APIView
|
||||
|
||||
|
||||
class HasPermissionView(APIView):
|
||||
url_prefix = "/validate"
|
||||
|
||||
@args_required("resource")
|
||||
@args_required("resource_type")
|
||||
@args_required("perm")
|
||||
def get(self):
|
||||
resource = request.values.get("resource")
|
||||
resource_type = request.values.get("resource_type")
|
||||
perm = request.values.get("perm")
|
||||
validate_permission(resource, resource_type, perm)
|
||||
return self.jsonify(is_valid=True)
|
||||
|
||||
def post(self):
|
||||
self.get()
|
||||
|
||||
|
||||
class GetResourcesView(APIView):
|
||||
url_prefix = "/resources"
|
||||
|
||||
@args_required("resource_type")
|
||||
def get(self):
|
||||
resource_type = request.values.get("resource_type")
|
||||
res = ACLManager().get_resources(resource_type)
|
||||
return self.jsonify(res)
|
||||
|
||||
|
||||
class GetUserInfoView(APIView):
|
||||
url_prefix = "/user/info"
|
||||
|
||||
def get(self):
|
||||
name = session.get("acl", {}).get("nickName") or session.get("CAS_USERNAME") or current_user.nickname
|
||||
role = dict(permissions=session.get("acl", {}).get("parentRoles", []) or ["admin"])
|
||||
avatar = session.get("acl", {}).get("avatar") or current_user.avatar
|
||||
return self.jsonify(result=dict(name=name,
|
||||
role=role,
|
||||
avatar=avatar))
|
Reference in New Issue
Block a user