mirror of https://github.com/veops/cmdb.git
Merge branch 'master' of github.com:veops/cmdb into dev_ui
This commit is contained in:
commit
88c9fb5ae3
|
@ -39,6 +39,7 @@ pip-log.txt
|
||||||
nosetests.xml
|
nosetests.xml
|
||||||
.pytest_cache
|
.pytest_cache
|
||||||
cmdb-api/test-output
|
cmdb-api/test-output
|
||||||
|
cmdb-api/api/uploaded_files
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
*.mo
|
*.mo
|
||||||
|
|
|
@ -9,7 +9,8 @@ from inspect import getmembers
|
||||||
from logging.handlers import RotatingFileHandler
|
from logging.handlers import RotatingFileHandler
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask import jsonify, make_response
|
from flask import jsonify
|
||||||
|
from flask import make_response
|
||||||
from flask.blueprints import Blueprint
|
from flask.blueprints import Blueprint
|
||||||
from flask.cli import click
|
from flask.cli import click
|
||||||
from flask.json.provider import DefaultJSONProvider
|
from flask.json.provider import DefaultJSONProvider
|
||||||
|
|
|
@ -10,8 +10,11 @@ from api.extensions import db
|
||||||
from api.lib.cmdb.cache import AttributeCache
|
from api.lib.cmdb.cache import AttributeCache
|
||||||
from api.lib.cmdb.cache import CITypeAttributesCache
|
from api.lib.cmdb.cache import CITypeAttributesCache
|
||||||
from api.lib.cmdb.cache import CITypeCache
|
from api.lib.cmdb.cache import CITypeCache
|
||||||
|
from api.lib.cmdb.const import BUILTIN_KEYWORDS
|
||||||
from api.lib.cmdb.const import CITypeOperateType
|
from api.lib.cmdb.const import CITypeOperateType
|
||||||
from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum
|
from api.lib.cmdb.const import PermEnum
|
||||||
|
from api.lib.cmdb.const import ResourceTypeEnum
|
||||||
|
from api.lib.cmdb.const import RoleEnum
|
||||||
from api.lib.cmdb.const import ValueTypeEnum
|
from api.lib.cmdb.const import ValueTypeEnum
|
||||||
from api.lib.cmdb.history import CITypeHistoryManager
|
from api.lib.cmdb.history import CITypeHistoryManager
|
||||||
from api.lib.cmdb.resp_format import ErrFormat
|
from api.lib.cmdb.resp_format import ErrFormat
|
||||||
|
@ -41,7 +44,7 @@ class AttributeManager(object):
|
||||||
ret_key = choice_web_hook.get('ret_key')
|
ret_key = choice_web_hook.get('ret_key')
|
||||||
headers = choice_web_hook.get('headers') or {}
|
headers = choice_web_hook.get('headers') or {}
|
||||||
payload = choice_web_hook.get('payload') or {}
|
payload = choice_web_hook.get('payload') or {}
|
||||||
method = choice_web_hook.get('method', 'GET').lower()
|
method = (choice_web_hook.get('method') or 'GET').lower()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = getattr(requests, method)(url, headers=headers, data=payload).json()
|
res = getattr(requests, method)(url, headers=headers, data=payload).json()
|
||||||
|
@ -56,15 +59,17 @@ class AttributeManager(object):
|
||||||
return [[i, {}] for i in (res.get(ret_key_list[-1]) or [])]
|
return [[i, {}] for i in (res.get(ret_key_list[-1]) or [])]
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
current_app.logger.error(str(e))
|
current_app.logger.error("get choice values failed: {}".format(e))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_choice_values(cls, attr_id, value_type, choice_web_hook, choice_web_hook_parse=True):
|
def get_choice_values(cls, attr_id, value_type, choice_web_hook, choice_web_hook_parse=True):
|
||||||
if choice_web_hook and isinstance(choice_web_hook, dict) and choice_web_hook_parse:
|
if choice_web_hook:
|
||||||
return cls._get_choice_values_from_web_hook(choice_web_hook)
|
if choice_web_hook_parse:
|
||||||
elif choice_web_hook and not choice_web_hook_parse:
|
if isinstance(choice_web_hook, dict):
|
||||||
return []
|
return cls._get_choice_values_from_web_hook(choice_web_hook)
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
choice_table = ValueTypeMap.choice.get(value_type)
|
choice_table = ValueTypeMap.choice.get(value_type)
|
||||||
choice_values = choice_table.get_by(fl=["value", "option"], attr_id=attr_id)
|
choice_values = choice_table.get_by(fl=["value", "option"], attr_id=attr_id)
|
||||||
|
@ -74,25 +79,25 @@ class AttributeManager(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_choice_values(_id, value_type, choice_values):
|
def add_choice_values(_id, value_type, choice_values):
|
||||||
choice_table = ValueTypeMap.choice.get(value_type)
|
choice_table = ValueTypeMap.choice.get(value_type)
|
||||||
|
if choice_table is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
choice_table.get_by(attr_id=_id, only_query=True).delete()
|
||||||
|
|
||||||
db.session.query(choice_table).filter(choice_table.attr_id == _id).delete()
|
|
||||||
db.session.flush()
|
|
||||||
choice_values = choice_values
|
|
||||||
for v, option in choice_values:
|
for v, option in choice_values:
|
||||||
table = choice_table(attr_id=_id, value=v, option=option)
|
choice_table.create(attr_id=_id, value=v, option=option, commit=False)
|
||||||
|
|
||||||
db.session.add(table)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db.session.flush()
|
db.session.flush()
|
||||||
except:
|
except Exception as e:
|
||||||
|
current_app.logger.warning("add choice values failed: {}".format(e))
|
||||||
return abort(400, ErrFormat.invalid_choice_values)
|
return abort(400, ErrFormat.invalid_choice_values)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _del_choice_values(_id, value_type):
|
def _del_choice_values(_id, value_type):
|
||||||
choice_table = ValueTypeMap.choice.get(value_type)
|
choice_table = ValueTypeMap.choice.get(value_type)
|
||||||
|
|
||||||
db.session.query(choice_table).filter(choice_table.attr_id == _id).delete()
|
choice_table and choice_table.get_by(attr_id=_id, only_query=True).delete()
|
||||||
db.session.flush()
|
db.session.flush()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -115,8 +120,8 @@ class AttributeManager(object):
|
||||||
attrs = attrs[(page - 1) * page_size:][:page_size]
|
attrs = attrs[(page - 1) * page_size:][:page_size]
|
||||||
res = list()
|
res = list()
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
attr["is_choice"] and attr.update(dict(choice_value=cls.get_choice_values(
|
attr["is_choice"] and attr.update(
|
||||||
attr["id"], attr["value_type"], attr["choice_web_hook"])))
|
dict(choice_value=cls.get_choice_values(attr["id"], attr["value_type"], attr["choice_web_hook"])))
|
||||||
attr['is_choice'] and attr.pop('choice_web_hook', None)
|
attr['is_choice'] and attr.pop('choice_web_hook', None)
|
||||||
|
|
||||||
res.append(attr)
|
res.append(attr)
|
||||||
|
@ -125,30 +130,31 @@ class AttributeManager(object):
|
||||||
|
|
||||||
def get_attribute_by_name(self, name):
|
def get_attribute_by_name(self, name):
|
||||||
attr = Attribute.get_by(name=name, first=True)
|
attr = Attribute.get_by(name=name, first=True)
|
||||||
if attr and attr["is_choice"]:
|
if attr.get("is_choice"):
|
||||||
attr.update(dict(choice_value=self.get_choice_values(
|
attr["choice_value"] = self.get_choice_values(attr["id"], attr["value_type"], attr["choice_web_hook"])
|
||||||
attr["id"], attr["value_type"], attr["choice_web_hook"])))
|
|
||||||
return attr
|
return attr
|
||||||
|
|
||||||
def get_attribute_by_alias(self, alias):
|
def get_attribute_by_alias(self, alias):
|
||||||
attr = Attribute.get_by(alias=alias, first=True)
|
attr = Attribute.get_by(alias=alias, first=True)
|
||||||
if attr and attr["is_choice"]:
|
if attr.get("is_choice"):
|
||||||
attr.update(dict(choice_value=self.get_choice_values(
|
attr["choice_value"] = self.get_choice_values(attr["id"], attr["value_type"], attr["choice_web_hook"])
|
||||||
attr["id"], attr["value_type"], attr["choice_web_hook"])))
|
|
||||||
return attr
|
return attr
|
||||||
|
|
||||||
def get_attribute_by_id(self, _id):
|
def get_attribute_by_id(self, _id):
|
||||||
attr = Attribute.get_by_id(_id).to_dict()
|
attr = Attribute.get_by_id(_id).to_dict()
|
||||||
if attr and attr["is_choice"]:
|
if attr.get("is_choice"):
|
||||||
attr.update(dict(choice_value=self.get_choice_values(
|
attr["choice_value"] = self.get_choice_values(attr["id"], attr["value_type"], attr["choice_web_hook"])
|
||||||
attr["id"], attr["value_type"], attr["choice_web_hook"])))
|
|
||||||
return attr
|
return attr
|
||||||
|
|
||||||
def get_attribute(self, key, choice_web_hook_parse=True):
|
def get_attribute(self, key, choice_web_hook_parse=True):
|
||||||
attr = AttributeCache.get(key).to_dict()
|
attr = AttributeCache.get(key).to_dict()
|
||||||
if attr and attr["is_choice"]:
|
if attr.get("is_choice"):
|
||||||
attr.update(dict(choice_value=self.get_choice_values(
|
attr["choice_value"] = self.get_choice_values(
|
||||||
attr["id"], attr["value_type"], attr["choice_web_hook"])), choice_web_hook_parse=choice_web_hook_parse)
|
attr["id"], attr["value_type"], attr["choice_web_hook"], choice_web_hook_parse=choice_web_hook_parse)
|
||||||
|
|
||||||
return attr
|
return attr
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -164,8 +170,9 @@ class AttributeManager(object):
|
||||||
is_choice = True if choice_value or kwargs.get('choice_web_hook') else False
|
is_choice = True if choice_value or kwargs.get('choice_web_hook') else False
|
||||||
|
|
||||||
name = kwargs.pop("name")
|
name = kwargs.pop("name")
|
||||||
if name in {'id', '_id', 'ci_id', 'type', '_type', 'ci_type'}:
|
if name in BUILTIN_KEYWORDS:
|
||||||
return abort(400, ErrFormat.attribute_name_cannot_be_builtin)
|
return abort(400, ErrFormat.attribute_name_cannot_be_builtin)
|
||||||
|
|
||||||
alias = kwargs.pop("alias", "")
|
alias = kwargs.pop("alias", "")
|
||||||
alias = name if not alias else alias
|
alias = name if not alias else alias
|
||||||
Attribute.get_by(name=name, first=True) and abort(400, ErrFormat.attribute_name_duplicate.format(name))
|
Attribute.get_by(name=name, first=True) and abort(400, ErrFormat.attribute_name_duplicate.format(name))
|
||||||
|
@ -218,7 +225,8 @@ class AttributeManager(object):
|
||||||
for i in CITypeAttribute.get_by(attr_id=attr_id, to_dict=False):
|
for i in CITypeAttribute.get_by(attr_id=attr_id, to_dict=False):
|
||||||
CITypeAttributesCache.clean(i.type_id)
|
CITypeAttributesCache.clean(i.type_id)
|
||||||
|
|
||||||
def _change_index(self, attr, old, new):
|
@staticmethod
|
||||||
|
def _change_index(attr, old, new):
|
||||||
from api.lib.cmdb.utils import TableMap
|
from api.lib.cmdb.utils import TableMap
|
||||||
from api.tasks.cmdb import batch_ci_cache
|
from api.tasks.cmdb import batch_ci_cache
|
||||||
from api.lib.cmdb.const import CMDB_QUEUE
|
from api.lib.cmdb.const import CMDB_QUEUE
|
||||||
|
@ -227,11 +235,11 @@ class AttributeManager(object):
|
||||||
new_table = TableMap(attr=attr, is_index=new).table
|
new_table = TableMap(attr=attr, is_index=new).table
|
||||||
|
|
||||||
ci_ids = []
|
ci_ids = []
|
||||||
for i in db.session.query(old_table).filter(getattr(old_table, 'attr_id') == attr.id):
|
for i in old_table.get_by(attr_id=attr.id, to_dict=False):
|
||||||
new_table.create(ci_id=i.ci_id, attr_id=attr.id, value=i.value, flush=True)
|
new_table.create(ci_id=i.ci_id, attr_id=attr.id, value=i.value, flush=True)
|
||||||
ci_ids.append(i.ci_id)
|
ci_ids.append(i.ci_id)
|
||||||
|
|
||||||
db.session.query(old_table).filter(getattr(old_table, 'attr_id') == attr.id).delete()
|
old_table.get_by(attr_id=attr.id, only_query=True).delete()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -296,7 +304,7 @@ class AttributeManager(object):
|
||||||
|
|
||||||
if is_choice and choice_value:
|
if is_choice and choice_value:
|
||||||
self.add_choice_values(attr.id, attr.value_type, choice_value)
|
self.add_choice_values(attr.id, attr.value_type, choice_value)
|
||||||
elif is_choice:
|
elif existed2['is_choice']:
|
||||||
self._del_choice_values(attr.id, attr.value_type)
|
self._del_choice_values(attr.id, attr.value_type)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -330,24 +338,25 @@ class AttributeManager(object):
|
||||||
ref = CITypeAttribute.get_by(attr_id=_id, to_dict=False, first=True)
|
ref = CITypeAttribute.get_by(attr_id=_id, to_dict=False, first=True)
|
||||||
if ref is not None:
|
if ref is not None:
|
||||||
ci_type = CITypeCache.get(ref.type_id)
|
ci_type = CITypeCache.get(ref.type_id)
|
||||||
return abort(400, ErrFormat.attribute_is_ref_by_type.format(ci_type.alias))
|
return abort(400, ErrFormat.attribute_is_ref_by_type.format(ci_type and ci_type.alias or ref.type_id))
|
||||||
|
|
||||||
if attr.uid != current_user.uid and not is_app_admin('cmdb'):
|
if attr.uid != current_user.uid and not is_app_admin('cmdb'):
|
||||||
return abort(403, ErrFormat.cannot_delete_attribute)
|
return abort(403, ErrFormat.cannot_delete_attribute)
|
||||||
|
|
||||||
if attr.is_choice:
|
if attr.is_choice:
|
||||||
choice_table = ValueTypeMap.choice.get(attr.value_type)
|
choice_table = ValueTypeMap.choice.get(attr.value_type)
|
||||||
db.session.query(choice_table).filter(choice_table.attr_id == _id).delete() # FIXME: session conflict
|
choice_table.get_by(attr_id=_id, only_query=True).delete()
|
||||||
db.session.flush()
|
|
||||||
|
|
||||||
AttributeCache.clean(attr)
|
|
||||||
|
|
||||||
attr.soft_delete()
|
attr.soft_delete()
|
||||||
|
|
||||||
|
AttributeCache.clean(attr)
|
||||||
|
|
||||||
for i in PreferenceShowAttributes.get_by(attr_id=_id, to_dict=False):
|
for i in PreferenceShowAttributes.get_by(attr_id=_id, to_dict=False):
|
||||||
i.soft_delete()
|
i.soft_delete(commit=False)
|
||||||
|
|
||||||
for i in CITypeAttributeGroupItem.get_by(attr_id=_id, to_dict=False):
|
for i in CITypeAttributeGroupItem.get_by(attr_id=_id, to_dict=False):
|
||||||
i.soft_delete()
|
i.soft_delete(commit=False)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
|
|
@ -240,9 +240,10 @@ class AutoDiscoveryCITypeCRUD(DBMixin):
|
||||||
try:
|
try:
|
||||||
response, _, _, _, _, _ = s.search()
|
response, _, _, _, _, _ = s.search()
|
||||||
for i in response:
|
for i in response:
|
||||||
if current_user.username not in (i.get('rd_duty') or []) and current_user.username not in \
|
if (current_user.username not in (i.get('rd_duty') or []) and
|
||||||
(i.get('op_duty') or []) and current_user.nickname not in (i.get('rd_duty') or []) and \
|
current_user.username not in (i.get('op_duty') or []) and
|
||||||
current_user.nickname not in (i.get('op_duty') or []):
|
current_user.nickname not in (i.get('rd_duty') or []) and
|
||||||
|
current_user.nickname not in (i.get('op_duty') or [])):
|
||||||
return abort(403, ErrFormat.adt_target_expr_no_permission.format(
|
return abort(403, ErrFormat.adt_target_expr_no_permission.format(
|
||||||
i.get("{}_name".format(i.get('ci_type')))))
|
i.get("{}_name".format(i.get('ci_type')))))
|
||||||
except SearchError as e:
|
except SearchError as e:
|
||||||
|
|
|
@ -34,6 +34,7 @@ class AttributeCache(object):
|
||||||
attr = attr or Attribute.get_by(alias=key, first=True, to_dict=False)
|
attr = attr or Attribute.get_by(alias=key, first=True, to_dict=False)
|
||||||
if attr is not None:
|
if attr is not None:
|
||||||
cls.set(attr)
|
cls.set(attr)
|
||||||
|
|
||||||
return attr
|
return attr
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -67,6 +68,7 @@ class CITypeCache(object):
|
||||||
ct = ct or CIType.get_by(alias=key, first=True, to_dict=False)
|
ct = ct or CIType.get_by(alias=key, first=True, to_dict=False)
|
||||||
if ct is not None:
|
if ct is not None:
|
||||||
cls.set(ct)
|
cls.set(ct)
|
||||||
|
|
||||||
return ct
|
return ct
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -98,6 +100,7 @@ class RelationTypeCache(object):
|
||||||
ct = RelationType.get_by(name=key, first=True, to_dict=False) or RelationType.get_by_id(key)
|
ct = RelationType.get_by(name=key, first=True, to_dict=False) or RelationType.get_by_id(key)
|
||||||
if ct is not None:
|
if ct is not None:
|
||||||
cls.set(ct)
|
cls.set(ct)
|
||||||
|
|
||||||
return ct
|
return ct
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -133,12 +136,15 @@ class CITypeAttributesCache(object):
|
||||||
attrs = attrs or cache.get(cls.PREFIX_ID.format(key))
|
attrs = attrs or cache.get(cls.PREFIX_ID.format(key))
|
||||||
if not attrs:
|
if not attrs:
|
||||||
attrs = CITypeAttribute.get_by(type_id=key, to_dict=False)
|
attrs = CITypeAttribute.get_by(type_id=key, to_dict=False)
|
||||||
|
|
||||||
if not attrs:
|
if not attrs:
|
||||||
ci_type = CIType.get_by(name=key, first=True, to_dict=False)
|
ci_type = CIType.get_by(name=key, first=True, to_dict=False)
|
||||||
if ci_type is not None:
|
if ci_type is not None:
|
||||||
attrs = CITypeAttribute.get_by(type_id=ci_type.id, to_dict=False)
|
attrs = CITypeAttribute.get_by(type_id=ci_type.id, to_dict=False)
|
||||||
|
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
cls.set(key, attrs)
|
cls.set(key, attrs)
|
||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -155,13 +161,16 @@ class CITypeAttributesCache(object):
|
||||||
attrs = attrs or cache.get(cls.PREFIX_ID2.format(key))
|
attrs = attrs or cache.get(cls.PREFIX_ID2.format(key))
|
||||||
if not attrs:
|
if not attrs:
|
||||||
attrs = CITypeAttribute.get_by(type_id=key, to_dict=False)
|
attrs = CITypeAttribute.get_by(type_id=key, to_dict=False)
|
||||||
|
|
||||||
if not attrs:
|
if not attrs:
|
||||||
ci_type = CIType.get_by(name=key, first=True, to_dict=False)
|
ci_type = CIType.get_by(name=key, first=True, to_dict=False)
|
||||||
if ci_type is not None:
|
if ci_type is not None:
|
||||||
attrs = CITypeAttribute.get_by(type_id=ci_type.id, to_dict=False)
|
attrs = CITypeAttribute.get_by(type_id=ci_type.id, to_dict=False)
|
||||||
|
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
attrs = [(i, AttributeCache.get(i.attr_id)) for i in attrs]
|
attrs = [(i, AttributeCache.get(i.attr_id)) for i in attrs]
|
||||||
cls.set2(key, attrs)
|
cls.set2(key, attrs)
|
||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -204,10 +213,11 @@ class CITypeAttributeCache(object):
|
||||||
|
|
||||||
attr = cache.get(cls.PREFIX_ID.format(type_id, attr_id))
|
attr = cache.get(cls.PREFIX_ID.format(type_id, attr_id))
|
||||||
attr = attr or cache.get(cls.PREFIX_ID.format(type_id, attr_id))
|
attr = attr or cache.get(cls.PREFIX_ID.format(type_id, attr_id))
|
||||||
if not attr:
|
attr = attr or CITypeAttribute.get_by(type_id=type_id, attr_id=attr_id, first=True, to_dict=False)
|
||||||
attr = CITypeAttribute.get_by(type_id=type_id, attr_id=attr_id, first=True, to_dict=False)
|
|
||||||
if attr is not None:
|
if attr is not None:
|
||||||
cls.set(type_id, attr_id, attr)
|
cls.set(type_id, attr_id, attr)
|
||||||
|
|
||||||
return attr
|
return attr
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -38,8 +38,8 @@ from api.lib.decorator import kwargs_required
|
||||||
from api.lib.perm.acl.acl import ACLManager
|
from api.lib.perm.acl.acl import ACLManager
|
||||||
from api.lib.perm.acl.acl import is_app_admin
|
from api.lib.perm.acl.acl import is_app_admin
|
||||||
from api.lib.perm.acl.acl import validate_permission
|
from api.lib.perm.acl.acl import validate_permission
|
||||||
from api.lib.utils import Lock
|
|
||||||
from api.lib.utils import handle_arg_list
|
from api.lib.utils import handle_arg_list
|
||||||
|
from api.lib.utils import Lock
|
||||||
from api.models.cmdb import AutoDiscoveryCI
|
from api.models.cmdb import AutoDiscoveryCI
|
||||||
from api.models.cmdb import CI
|
from api.models.cmdb import CI
|
||||||
from api.models.cmdb import CIRelation
|
from api.models.cmdb import CIRelation
|
||||||
|
@ -67,11 +67,13 @@ class CIManager(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_type_name(ci_id):
|
def get_type_name(ci_id):
|
||||||
ci = CI.get_by_id(ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id)))
|
ci = CI.get_by_id(ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id)))
|
||||||
|
|
||||||
return CITypeCache.get(ci.type_id).name
|
return CITypeCache.get(ci.type_id).name
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_type(ci_id):
|
def get_type(ci_id):
|
||||||
ci = CI.get_by_id(ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id)))
|
ci = CI.get_by_id(ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id)))
|
||||||
|
|
||||||
return CITypeCache.get(ci.type_id)
|
return CITypeCache.get(ci.type_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -93,9 +95,7 @@ class CIManager(object):
|
||||||
|
|
||||||
res = dict()
|
res = dict()
|
||||||
|
|
||||||
if need_children:
|
need_children and res.update(CIRelationManager.get_children(ci_id, ret_key=ret_key)) # one floor
|
||||||
children = CIRelationManager.get_children(ci_id, ret_key=ret_key) # one floor
|
|
||||||
res.update(children)
|
|
||||||
|
|
||||||
ci_type = CITypeCache.get(ci.type_id)
|
ci_type = CITypeCache.get(ci.type_id)
|
||||||
res["ci_type"] = ci_type.name
|
res["ci_type"] = ci_type.name
|
||||||
|
@ -162,14 +162,11 @@ class CIManager(object):
|
||||||
|
|
||||||
ci = CI.get_by_id(ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id)))
|
ci = CI.get_by_id(ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id)))
|
||||||
|
|
||||||
if valid:
|
valid and cls.valid_ci_only_read(ci)
|
||||||
cls.valid_ci_only_read(ci)
|
|
||||||
|
|
||||||
res = dict()
|
res = dict()
|
||||||
|
|
||||||
if need_children:
|
need_children and res.update(CIRelationManager.get_children(ci_id, ret_key=ret_key)) # one floor
|
||||||
children = CIRelationManager.get_children(ci_id, ret_key=ret_key) # one floor
|
|
||||||
res.update(children)
|
|
||||||
|
|
||||||
ci_type = CITypeCache.get(ci.type_id)
|
ci_type = CITypeCache.get(ci.type_id)
|
||||||
res["ci_type"] = ci_type.name
|
res["ci_type"] = ci_type.name
|
||||||
|
@ -248,7 +245,7 @@ class CIManager(object):
|
||||||
for i in unique_constraints:
|
for i in unique_constraints:
|
||||||
attr_ids.extend(i.attr_ids)
|
attr_ids.extend(i.attr_ids)
|
||||||
|
|
||||||
attrs = [AttributeCache.get(i) for i in list(set(attr_ids))]
|
attrs = [AttributeCache.get(i) for i in set(attr_ids)]
|
||||||
id2name = {i.id: i.name for i in attrs if i}
|
id2name = {i.id: i.name for i in attrs if i}
|
||||||
not_existed_fields = list(set(id2name.values()) - set(ci_dict.keys()))
|
not_existed_fields = list(set(id2name.values()) - set(ci_dict.keys()))
|
||||||
if not_existed_fields and ci_id is not None:
|
if not_existed_fields and ci_id is not None:
|
||||||
|
@ -333,10 +330,6 @@ class CIManager(object):
|
||||||
if exist_policy == ExistPolicy.NEED:
|
if exist_policy == ExistPolicy.NEED:
|
||||||
return abort(404, ErrFormat.ci_not_found.format("{}={}".format(unique_key.name, unique_value)))
|
return abort(404, ErrFormat.ci_not_found.format("{}={}".format(unique_key.name, unique_value)))
|
||||||
|
|
||||||
from api.lib.cmdb.const import L_CI
|
|
||||||
if L_CI and len(CI.get_by(type_id=ci_type.id)) > L_CI * 2:
|
|
||||||
return abort(400, ErrFormat.limit_ci.format(L_CI * 2))
|
|
||||||
|
|
||||||
limit_attrs = cls._valid_ci_for_no_read(ci, ci_type) if not _is_admin else {}
|
limit_attrs = cls._valid_ci_for_no_read(ci, ci_type) if not _is_admin else {}
|
||||||
|
|
||||||
if existed is None: # set default
|
if existed is None: # set default
|
||||||
|
@ -368,12 +361,12 @@ class CIManager(object):
|
||||||
cls._valid_unique_constraint(ci_type.id, ci_dict, ci and ci.id)
|
cls._valid_unique_constraint(ci_type.id, ci_dict, ci and ci.id)
|
||||||
|
|
||||||
for k in ci_dict:
|
for k in ci_dict:
|
||||||
if k not in ci_type_attrs_name and k not in ci_type_attrs_alias and \
|
if k not in ci_type_attrs_name and (
|
||||||
_no_attribute_policy == ExistPolicy.REJECT:
|
k not in ci_type_attrs_alias and _no_attribute_policy == ExistPolicy.REJECT):
|
||||||
return abort(400, ErrFormat.attribute_not_found.format(k))
|
return abort(400, ErrFormat.attribute_not_found.format(k))
|
||||||
|
|
||||||
if limit_attrs and ci_type_attrs_name.get(k) not in limit_attrs and \
|
if limit_attrs and ci_type_attrs_name.get(k) not in limit_attrs and (
|
||||||
ci_type_attrs_alias.get(k) not in limit_attrs:
|
ci_type_attrs_alias.get(k) not in limit_attrs):
|
||||||
return abort(403, ErrFormat.ci_filter_perm_attr_no_permission.format(k))
|
return abort(403, ErrFormat.ci_filter_perm_attr_no_permission.format(k))
|
||||||
|
|
||||||
ci_dict = {k: v for k, v in ci_dict.items() if k in ci_type_attrs_name or k in ci_type_attrs_alias}
|
ci_dict = {k: v for k, v in ci_dict.items() if k in ci_type_attrs_name or k in ci_type_attrs_alias}
|
||||||
|
@ -486,11 +479,11 @@ class CIManager(object):
|
||||||
unique_key = AttributeCache.get(ci_type.unique_id)
|
unique_key = AttributeCache.get(ci_type.unique_id)
|
||||||
value_table = TableMap(attr=unique_key).table
|
value_table = TableMap(attr=unique_key).table
|
||||||
|
|
||||||
v = value_table.get_by(attr_id=unique_key.id,
|
v = (value_table.get_by(attr_id=unique_key.id,
|
||||||
value=unique_value,
|
value=unique_value,
|
||||||
to_dict=False,
|
to_dict=False,
|
||||||
first=True) \
|
first=True) or
|
||||||
or abort(404, ErrFormat.not_found)
|
abort(404, ErrFormat.not_found))
|
||||||
|
|
||||||
ci = CI.get_by_id(v.ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(v.ci_id)))
|
ci = CI.get_by_id(v.ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(v.ci_id)))
|
||||||
|
|
||||||
|
@ -536,6 +529,7 @@ class CIManager(object):
|
||||||
result = [(i.get("hostname"), i.get("private_ip")[0], i.get("ci_type"),
|
result = [(i.get("hostname"), i.get("private_ip")[0], i.get("ci_type"),
|
||||||
heartbeat_dict.get(i.get("_id"))) for i in res
|
heartbeat_dict.get(i.get("_id"))) for i in res
|
||||||
if i.get("private_ip")]
|
if i.get("private_ip")]
|
||||||
|
|
||||||
return numfound, result
|
return numfound, result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -655,6 +649,7 @@ class CIManager(object):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
current_app.logger.warning("cache not hit...............")
|
current_app.logger.warning("cache not hit...............")
|
||||||
|
|
||||||
return cls._get_cis_from_db(ci_ids, ret_key, fields, value_tables, excludes=excludes)
|
return cls._get_cis_from_db(ci_ids, ret_key, fields, value_tables, excludes=excludes)
|
||||||
|
|
||||||
|
|
||||||
|
@ -680,6 +675,7 @@ class CIRelationManager(object):
|
||||||
ci_type = CITypeCache.get(type_id)
|
ci_type = CITypeCache.get(type_id)
|
||||||
children = CIManager.get_cis_by_ids(list(map(str, ci_type2ci_ids[type_id])), ret_key=ret_key)
|
children = CIManager.get_cis_by_ids(list(map(str, ci_type2ci_ids[type_id])), ret_key=ret_key)
|
||||||
res[ci_type.name] = children
|
res[ci_type.name] = children
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -856,12 +852,12 @@ class CIRelationManager(object):
|
||||||
:param children:
|
:param children:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if parents is not None and isinstance(parents, list):
|
if isinstance(parents, list):
|
||||||
for parent_id in parents:
|
for parent_id in parents:
|
||||||
for ci_id in ci_ids:
|
for ci_id in ci_ids:
|
||||||
cls.add(parent_id, ci_id)
|
cls.add(parent_id, ci_id)
|
||||||
|
|
||||||
if children is not None and isinstance(children, list):
|
if isinstance(children, list):
|
||||||
for child_id in children:
|
for child_id in children:
|
||||||
for ci_id in ci_ids:
|
for ci_id in ci_ids:
|
||||||
cls.add(ci_id, child_id)
|
cls.add(ci_id, child_id)
|
||||||
|
@ -875,7 +871,7 @@ class CIRelationManager(object):
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if parents is not None and isinstance(parents, list):
|
if isinstance(parents, list):
|
||||||
for parent_id in parents:
|
for parent_id in parents:
|
||||||
for ci_id in ci_ids:
|
for ci_id in ci_ids:
|
||||||
cls.delete_2(parent_id, ci_id)
|
cls.delete_2(parent_id, ci_id)
|
||||||
|
|
|
@ -16,7 +16,9 @@ from api.lib.cmdb.cache import CITypeCache
|
||||||
from api.lib.cmdb.const import CITypeOperateType
|
from api.lib.cmdb.const import CITypeOperateType
|
||||||
from api.lib.cmdb.const import CMDB_QUEUE
|
from api.lib.cmdb.const import CMDB_QUEUE
|
||||||
from api.lib.cmdb.const import ConstraintEnum
|
from api.lib.cmdb.const import ConstraintEnum
|
||||||
from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum
|
from api.lib.cmdb.const import PermEnum
|
||||||
|
from api.lib.cmdb.const import ResourceTypeEnum
|
||||||
|
from api.lib.cmdb.const import RoleEnum
|
||||||
from api.lib.cmdb.const import ValueTypeEnum
|
from api.lib.cmdb.const import ValueTypeEnum
|
||||||
from api.lib.cmdb.history import CITypeHistoryManager
|
from api.lib.cmdb.history import CITypeHistoryManager
|
||||||
from api.lib.cmdb.relation_type import RelationTypeManager
|
from api.lib.cmdb.relation_type import RelationTypeManager
|
||||||
|
@ -60,6 +62,7 @@ class CITypeManager(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_name_by_id(type_id):
|
def get_name_by_id(type_id):
|
||||||
ci_type = CITypeCache.get(type_id)
|
ci_type = CITypeCache.get(type_id)
|
||||||
|
|
||||||
return ci_type and ci_type.name
|
return ci_type and ci_type.name
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -71,7 +74,7 @@ class CITypeManager(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_ci_types(type_name=None):
|
def get_ci_types(type_name=None):
|
||||||
resources = None
|
resources = None
|
||||||
if current_app.config.get('USE_ACL') and not is_app_admin():
|
if current_app.config.get('USE_ACL') and not is_app_admin('cmdb'):
|
||||||
resources = set([i.get('name') for i in ACLManager().get_resources("CIType")])
|
resources = set([i.get('name') for i in ACLManager().get_resources("CIType")])
|
||||||
|
|
||||||
ci_types = CIType.get_by() if type_name is None else CIType.get_by_like(name=type_name)
|
ci_types = CIType.get_by() if type_name is None else CIType.get_by_like(name=type_name)
|
||||||
|
@ -110,9 +113,6 @@ class CITypeManager(object):
|
||||||
@classmethod
|
@classmethod
|
||||||
@kwargs_required("name")
|
@kwargs_required("name")
|
||||||
def add(cls, **kwargs):
|
def add(cls, **kwargs):
|
||||||
from api.lib.cmdb.const import L_TYPE
|
|
||||||
if L_TYPE and len(CIType.get_by()) > L_TYPE * 2:
|
|
||||||
return abort(400, ErrFormat.limit_ci_type.format(L_TYPE * 2))
|
|
||||||
|
|
||||||
unique_key = kwargs.pop("unique_key", None)
|
unique_key = kwargs.pop("unique_key", None)
|
||||||
unique_key = AttributeCache.get(unique_key) or abort(404, ErrFormat.unique_key_not_define)
|
unique_key = AttributeCache.get(unique_key) or abort(404, ErrFormat.unique_key_not_define)
|
||||||
|
@ -184,6 +184,7 @@ class CITypeManager(object):
|
||||||
def set_enabled(cls, type_id, enabled=True):
|
def set_enabled(cls, type_id, enabled=True):
|
||||||
ci_type = cls.check_is_existed(type_id)
|
ci_type = cls.check_is_existed(type_id)
|
||||||
ci_type.update(enabled=enabled)
|
ci_type.update(enabled=enabled)
|
||||||
|
|
||||||
return type_id
|
return type_id
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -268,6 +269,7 @@ class CITypeGroupManager(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add(name):
|
def add(name):
|
||||||
CITypeGroup.get_by(name=name, first=True) and abort(400, ErrFormat.ci_type_group_exists.format(name))
|
CITypeGroup.get_by(name=name, first=True) and abort(400, ErrFormat.ci_type_group_exists.format(name))
|
||||||
|
|
||||||
return CITypeGroup.create(name=name)
|
return CITypeGroup.create(name=name)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -354,6 +356,7 @@ class CITypeAttributeManager(object):
|
||||||
attr_dict.pop('choice_web_hook', None)
|
attr_dict.pop('choice_web_hook', None)
|
||||||
|
|
||||||
result.append(attr_dict)
|
result.append(attr_dict)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -541,6 +544,7 @@ class CITypeRelationManager(object):
|
||||||
ci_type_dict["attributes"] = CITypeAttributeManager.get_attributes_by_type_id(ci_type_dict["id"])
|
ci_type_dict["attributes"] = CITypeAttributeManager.get_attributes_by_type_id(ci_type_dict["id"])
|
||||||
ci_type_dict["relation_type"] = relation_inst.relation_type.name
|
ci_type_dict["relation_type"] = relation_inst.relation_type.name
|
||||||
ci_type_dict["constraint"] = relation_inst.constraint
|
ci_type_dict["constraint"] = relation_inst.constraint
|
||||||
|
|
||||||
return ci_type_dict
|
return ci_type_dict
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -599,8 +603,8 @@ class CITypeRelationManager(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete(cls, _id):
|
def delete(cls, _id):
|
||||||
ctr = CITypeRelation.get_by_id(_id) or \
|
ctr = (CITypeRelation.get_by_id(_id) or
|
||||||
abort(404, ErrFormat.ci_type_relation_not_found.format("id={}".format(_id)))
|
abort(404, ErrFormat.ci_type_relation_not_found.format("id={}".format(_id))))
|
||||||
ctr.soft_delete()
|
ctr.soft_delete()
|
||||||
|
|
||||||
CITypeHistoryManager.add(CITypeOperateType.DELETE_RELATION, ctr.parent_id,
|
CITypeHistoryManager.add(CITypeOperateType.DELETE_RELATION, ctr.parent_id,
|
||||||
|
@ -654,6 +658,7 @@ class CITypeAttributeGroupManager(object):
|
||||||
:param name:
|
:param name:
|
||||||
:param group_order: group order
|
:param group_order: group order
|
||||||
:param attr_order:
|
:param attr_order:
|
||||||
|
:param is_update:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
existed = CITypeAttributeGroup.get_by(type_id=type_id, name=name, first=True, to_dict=False)
|
existed = CITypeAttributeGroup.get_by(type_id=type_id, name=name, first=True, to_dict=False)
|
||||||
|
@ -694,8 +699,8 @@ class CITypeAttributeGroupManager(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete(group_id):
|
def delete(group_id):
|
||||||
group = CITypeAttributeGroup.get_by_id(group_id) \
|
group = (CITypeAttributeGroup.get_by_id(group_id) or
|
||||||
or abort(404, ErrFormat.ci_type_attribute_group_not_found.format("id={}".format(group_id)))
|
abort(404, ErrFormat.ci_type_attribute_group_not_found.format("id={}".format(group_id))))
|
||||||
group.soft_delete()
|
group.soft_delete()
|
||||||
|
|
||||||
items = CITypeAttributeGroupItem.get_by(group_id=group_id, to_dict=False)
|
items = CITypeAttributeGroupItem.get_by(group_id=group_id, to_dict=False)
|
||||||
|
@ -964,8 +969,8 @@ class CITypeTemplateManager(object):
|
||||||
rule['uid'] = current_user.uid
|
rule['uid'] = current_user.uid
|
||||||
try:
|
try:
|
||||||
AutoDiscoveryCITypeCRUD.add(**rule)
|
AutoDiscoveryCITypeCRUD.add(**rule)
|
||||||
except:
|
except Exception as e:
|
||||||
pass
|
current_app.logger.warning("import auto discovery rules failed: {}".format(e))
|
||||||
|
|
||||||
def import_template(self, tpt):
|
def import_template(self, tpt):
|
||||||
import time
|
import time
|
||||||
|
@ -1124,8 +1129,8 @@ class CITypeTriggerManager(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update(_id, notify):
|
def update(_id, notify):
|
||||||
existed = CITypeTrigger.get_by_id(_id) or \
|
existed = (CITypeTrigger.get_by_id(_id) or
|
||||||
abort(404, ErrFormat.ci_type_trigger_not_found.format("id={}".format(_id)))
|
abort(404, ErrFormat.ci_type_trigger_not_found.format("id={}".format(_id))))
|
||||||
|
|
||||||
existed2 = existed.to_dict()
|
existed2 = existed.to_dict()
|
||||||
new = existed.update(notify=notify)
|
new = existed.update(notify=notify)
|
||||||
|
@ -1139,8 +1144,8 @@ class CITypeTriggerManager(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete(_id):
|
def delete(_id):
|
||||||
existed = CITypeTrigger.get_by_id(_id) or \
|
existed = (CITypeTrigger.get_by_id(_id) or
|
||||||
abort(404, ErrFormat.ci_type_trigger_not_found.format("id={}".format(_id)))
|
abort(404, ErrFormat.ci_type_trigger_not_found.format("id={}".format(_id))))
|
||||||
|
|
||||||
existed.soft_delete()
|
existed.soft_delete()
|
||||||
|
|
||||||
|
@ -1163,16 +1168,16 @@ class CITypeTriggerManager(object):
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for v in values:
|
for v in values:
|
||||||
if isinstance(v.value, (datetime.date, datetime.datetime)) and \
|
if (isinstance(v.value, (datetime.date, datetime.datetime)) and
|
||||||
(v.value - delta_time).strftime('%Y%m%d') == now.strftime("%Y%m%d"):
|
(v.value - delta_time).strftime('%Y%m%d') == now.strftime("%Y%m%d")):
|
||||||
result.append(v)
|
result.append(v)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def trigger_notify(trigger, ci):
|
def trigger_notify(trigger, ci):
|
||||||
if trigger.notify.get('notify_at') == datetime.datetime.now().strftime("%H:%M") or \
|
if (trigger.notify.get('notify_at') == datetime.datetime.now().strftime("%H:%M") or
|
||||||
not trigger.notify.get('notify_at'):
|
not trigger.notify.get('notify_at')):
|
||||||
from api.tasks.cmdb import trigger_notify
|
from api.tasks.cmdb import trigger_notify
|
||||||
|
|
||||||
trigger_notify.apply_async(args=(trigger.notify, ci.ci_id), queue=CMDB_QUEUE)
|
trigger_notify.apply_async(args=(trigger.notify, ci.ci_id), queue=CMDB_QUEUE)
|
||||||
|
|
|
@ -99,5 +99,7 @@ CMDB_QUEUE = "one_cmdb_async"
|
||||||
REDIS_PREFIX_CI = "ONE_CMDB"
|
REDIS_PREFIX_CI = "ONE_CMDB"
|
||||||
REDIS_PREFIX_CI_RELATION = "CMDB_CI_RELATION"
|
REDIS_PREFIX_CI_RELATION = "CMDB_CI_RELATION"
|
||||||
|
|
||||||
|
BUILTIN_KEYWORDS = {'id', '_id', 'ci_id', 'type', '_type', 'ci_type'}
|
||||||
|
|
||||||
L_TYPE = None
|
L_TYPE = None
|
||||||
L_CI = None
|
L_CI = None
|
||||||
|
|
|
@ -176,8 +176,8 @@ class AttributeHistoryManger(object):
|
||||||
def get_record_detail(record_id):
|
def get_record_detail(record_id):
|
||||||
from api.lib.cmdb.ci import CIManager
|
from api.lib.cmdb.ci import CIManager
|
||||||
|
|
||||||
record = OperationRecord.get_by_id(record_id) or \
|
record = (OperationRecord.get_by_id(record_id) or
|
||||||
abort(404, ErrFormat.record_not_found.format("id={}".format(record_id)))
|
abort(404, ErrFormat.record_not_found.format("id={}".format(record_id))))
|
||||||
|
|
||||||
username = UserCache.get(record.uid).nickname or UserCache.get(record.uid).username
|
username = UserCache.get(record.uid).nickname or UserCache.get(record.uid).username
|
||||||
timestamp = record.created_at.strftime("%Y-%m-%d %H:%M:%S")
|
timestamp = record.created_at.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
|
@ -37,10 +37,12 @@ class PreferenceManager(object):
|
||||||
def get_types(instance=False, tree=False):
|
def get_types(instance=False, tree=False):
|
||||||
types = db.session.query(PreferenceShowAttributes.type_id).filter(
|
types = db.session.query(PreferenceShowAttributes.type_id).filter(
|
||||||
PreferenceShowAttributes.uid == current_user.uid).filter(
|
PreferenceShowAttributes.uid == current_user.uid).filter(
|
||||||
PreferenceShowAttributes.deleted.is_(False)).group_by(PreferenceShowAttributes.type_id).all() \
|
PreferenceShowAttributes.deleted.is_(False)).group_by(
|
||||||
if instance else []
|
PreferenceShowAttributes.type_id).all() if instance else []
|
||||||
|
|
||||||
tree_types = PreferenceTreeView.get_by(uid=current_user.uid, to_dict=False) if tree else []
|
tree_types = PreferenceTreeView.get_by(uid=current_user.uid, to_dict=False) if tree else []
|
||||||
type_ids = list(set([i.type_id for i in types + tree_types]))
|
type_ids = set([i.type_id for i in types + tree_types])
|
||||||
|
|
||||||
return [CITypeCache.get(type_id).to_dict() for type_id in type_ids]
|
return [CITypeCache.get(type_id).to_dict() for type_id in type_ids]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -24,21 +24,21 @@ class RelationTypeManager(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add(name):
|
def add(name):
|
||||||
RelationType.get_by(name=name, first=True, to_dict=False) and \
|
RelationType.get_by(name=name, first=True, to_dict=False) and abort(
|
||||||
abort(400, ErrFormat.relation_type_exists.format(name))
|
400, ErrFormat.relation_type_exists.format(name))
|
||||||
|
|
||||||
return RelationType.create(name=name)
|
return RelationType.create(name=name)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update(rel_id, name):
|
def update(rel_id, name):
|
||||||
existed = RelationType.get_by_id(rel_id) or \
|
existed = RelationType.get_by_id(rel_id) or abort(
|
||||||
abort(404, ErrFormat.relation_type_not_found.format("id={}".format(rel_id)))
|
404, ErrFormat.relation_type_not_found.format("id={}".format(rel_id)))
|
||||||
|
|
||||||
return existed.update(name=name)
|
return existed.update(name=name)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete(rel_id):
|
def delete(rel_id):
|
||||||
existed = RelationType.get_by_id(rel_id) or \
|
existed = RelationType.get_by_id(rel_id) or abort(
|
||||||
abort(404, ErrFormat.relation_type_not_found.format("id={}".format(rel_id)))
|
404, ErrFormat.relation_type_not_found.format("id={}".format(rel_id)))
|
||||||
|
|
||||||
existed.soft_delete()
|
existed.soft_delete()
|
||||||
|
|
|
@ -245,10 +245,8 @@ class Search(object):
|
||||||
new_table = _v_query_sql
|
new_table = _v_query_sql
|
||||||
|
|
||||||
if self.only_type_query or not self.type_id_list:
|
if self.only_type_query or not self.type_id_list:
|
||||||
return "SELECT SQL_CALC_FOUND_ROWS DISTINCT C.ci_id " \
|
return ("SELECT SQL_CALC_FOUND_ROWS DISTINCT C.ci_id FROM ({0}) AS C ORDER BY C.value {2} "
|
||||||
"FROM ({0}) AS C " \
|
"LIMIT {1:d}, {3};".format(new_table, (self.page - 1) * self.count, sort_type, self.count))
|
||||||
"ORDER BY C.value {2} " \
|
|
||||||
"LIMIT {1:d}, {3};".format(new_table, (self.page - 1) * self.count, sort_type, self.count)
|
|
||||||
|
|
||||||
elif self.type_id_list:
|
elif self.type_id_list:
|
||||||
self.query_sql = """SELECT C.ci_id
|
self.query_sql = """SELECT C.ci_id
|
||||||
|
|
|
@ -297,8 +297,8 @@ class Search(object):
|
||||||
if not attr:
|
if not attr:
|
||||||
raise SearchError(ErrFormat.attribute_not_found.format(field))
|
raise SearchError(ErrFormat.attribute_not_found.format(field))
|
||||||
|
|
||||||
sort_by = "{0}.keyword".format(field) \
|
sort_by = ("{0}.keyword".format(field)
|
||||||
if attr.value_type not in (ValueTypeEnum.INT, ValueTypeEnum.FLOAT) else field
|
if attr.value_type not in (ValueTypeEnum.INT, ValueTypeEnum.FLOAT) else field)
|
||||||
sorts.append({sort_by: {"order": sort_type}})
|
sorts.append({sort_by: {"order": sort_type}})
|
||||||
|
|
||||||
self.query.update(dict(sort=sorts))
|
self.query.update(dict(sort=sorts))
|
||||||
|
|
|
@ -83,6 +83,7 @@ class AttributeValueManager(object):
|
||||||
def __deserialize_value(value_type, value):
|
def __deserialize_value(value_type, value):
|
||||||
if not value:
|
if not value:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
deserialize = ValueTypeMap.deserialize[value_type]
|
deserialize = ValueTypeMap.deserialize[value_type]
|
||||||
try:
|
try:
|
||||||
v = deserialize(value)
|
v = deserialize(value)
|
||||||
|
@ -184,8 +185,8 @@ class AttributeValueManager(object):
|
||||||
return [var for var in schema.get("properties")]
|
return [var for var in schema.get("properties")]
|
||||||
|
|
||||||
def _compute_attr_value(self, attr, payload, ci):
|
def _compute_attr_value(self, attr, payload, ci):
|
||||||
attrs = self._jinja2_parse(attr['compute_expr']) if attr.get('compute_expr') else \
|
attrs = (self._jinja2_parse(attr['compute_expr']) if attr.get('compute_expr')
|
||||||
self._jinja2_parse(attr['compute_script'])
|
else self._jinja2_parse(attr['compute_script']))
|
||||||
not_existed = [i for i in attrs if i not in payload]
|
not_existed = [i for i in attrs if i not in payload]
|
||||||
if ci is not None:
|
if ci is not None:
|
||||||
payload.update(self.get_attr_values(not_existed, ci.id))
|
payload.update(self.get_attr_values(not_existed, ci.id))
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
from flask import abort
|
||||||
|
|
||||||
|
from api.extensions import db
|
||||||
|
from api.lib.common_setting.resp_format import ErrFormat
|
||||||
|
from api.models.common_setting import CommonData
|
||||||
|
|
||||||
|
|
||||||
|
class CommonDataCRUD(object):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_data_by_type(data_type):
|
||||||
|
return CommonData.get_by(data_type=data_type)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_data_by_id(_id, to_dict=True):
|
||||||
|
return CommonData.get_by(first=True, id=_id, to_dict=to_dict)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_new_data(data_type, **kwargs):
|
||||||
|
try:
|
||||||
|
return CommonData.create(data_type=data_type, **kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
abort(400, str(e))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_data(_id, **kwargs):
|
||||||
|
existed = CommonDataCRUD.get_data_by_id(_id, to_dict=False)
|
||||||
|
if not existed:
|
||||||
|
abort(404, ErrFormat.common_data_not_found.format(_id))
|
||||||
|
try:
|
||||||
|
return existed.update(**kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
abort(400, str(e))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def delete(_id):
|
||||||
|
existed = CommonDataCRUD.get_data_by_id(_id, to_dict=False)
|
||||||
|
if not existed:
|
||||||
|
abort(404, ErrFormat.common_data_not_found.format(_id))
|
||||||
|
try:
|
||||||
|
existed.soft_delete()
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
abort(400, str(e))
|
|
@ -54,3 +54,4 @@ class ErrFormat(CommonErrFormat):
|
||||||
email_is_required = "邮箱不能为空"
|
email_is_required = "邮箱不能为空"
|
||||||
email_format_error = "邮箱格式错误"
|
email_format_error = "邮箱格式错误"
|
||||||
|
|
||||||
|
common_data_not_found = "ID {} 找不到记录"
|
||||||
|
|
|
@ -4,8 +4,7 @@ from api.lib.common_setting.utils import get_cur_time_str
|
||||||
|
|
||||||
|
|
||||||
def allowed_file(filename, allowed_extensions):
|
def allowed_file(filename, allowed_extensions):
|
||||||
return '.' in filename and \
|
return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowed_extensions
|
||||||
filename.rsplit('.', 1)[1].lower() in allowed_extensions
|
|
||||||
|
|
||||||
|
|
||||||
def generate_new_file_name(name):
|
def generate_new_file_name(name):
|
||||||
|
@ -13,4 +12,5 @@ def generate_new_file_name(name):
|
||||||
prev_name = ''.join(name.split(f".{ext}")[:-1])
|
prev_name = ''.join(name.split(f".{ext}")[:-1])
|
||||||
uid = str(uuid.uuid4())
|
uid = str(uuid.uuid4())
|
||||||
cur_str = get_cur_time_str('_')
|
cur_str = get_cur_time_str('_')
|
||||||
|
|
||||||
return f"{prev_name}_{cur_str}_{uid}.{ext}"
|
return f"{prev_name}_{cur_str}_{uid}.{ext}"
|
||||||
|
|
|
@ -55,8 +55,8 @@ def args_validate(model_cls, exclude_args=None):
|
||||||
if exclude_args and arg in exclude_args:
|
if exclude_args and arg in exclude_args:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if attr.type.python_type == str and attr.type.length and \
|
if attr.type.python_type == str and attr.type.length and (
|
||||||
len(request.values[arg] or '') > attr.type.length:
|
len(request.values[arg] or '') > attr.type.length):
|
||||||
|
|
||||||
return abort(400, CommonErrFormat.argument_str_length_limit.format(arg, attr.type.length))
|
return abort(400, CommonErrFormat.argument_str_length_limit.format(arg, attr.type.length))
|
||||||
elif attr.type.python_type in (int, float) and request.values[arg]:
|
elif attr.type.python_type in (int, float) and request.values[arg]:
|
||||||
|
|
|
@ -5,8 +5,10 @@ import hashlib
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import six
|
import six
|
||||||
from flask import abort, session
|
from flask import abort
|
||||||
from flask import current_app, request
|
from flask import current_app
|
||||||
|
from flask import request
|
||||||
|
from flask import session
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
from api.extensions import cache
|
from api.extensions import cache
|
||||||
|
@ -85,8 +87,8 @@ class ACLManager(object):
|
||||||
if user:
|
if user:
|
||||||
return Role.get_by(name=name, uid=user.uid, first=True, to_dict=False)
|
return Role.get_by(name=name, uid=user.uid, first=True, to_dict=False)
|
||||||
|
|
||||||
return Role.get_by(name=name, app_id=self.app_id, first=True, to_dict=False) or \
|
return (Role.get_by(name=name, app_id=self.app_id, first=True, to_dict=False) or
|
||||||
Role.get_by(name=name, first=True, to_dict=False)
|
Role.get_by(name=name, first=True, to_dict=False))
|
||||||
|
|
||||||
def add_resource(self, name, resource_type_name=None):
|
def add_resource(self, name, resource_type_name=None):
|
||||||
resource_type = ResourceType.get_by(name=resource_type_name, first=True, to_dict=False)
|
resource_type = ResourceType.get_by(name=resource_type_name, first=True, to_dict=False)
|
||||||
|
|
|
@ -8,7 +8,9 @@ from flask import abort
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
from api.extensions import db
|
from api.extensions import db
|
||||||
from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType, AuditScope
|
from api.lib.perm.acl.audit import AuditCRUD
|
||||||
|
from api.lib.perm.acl.audit import AuditOperateType
|
||||||
|
from api.lib.perm.acl.audit import AuditScope
|
||||||
from api.lib.perm.acl.resp_format import ErrFormat
|
from api.lib.perm.acl.resp_format import ErrFormat
|
||||||
from api.models.acl import App
|
from api.models.acl import App
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,16 @@ from flask_login import current_user
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
|
|
||||||
from api.lib.perm.acl import AppCache
|
from api.lib.perm.acl import AppCache
|
||||||
from api.models.acl import AuditPermissionLog, AuditResourceLog, AuditRoleLog, AuditTriggerLog, Permission, Resource, \
|
from api.models.acl import AuditPermissionLog
|
||||||
ResourceGroup, ResourceType, Role, RolePermission
|
from api.models.acl import AuditResourceLog
|
||||||
|
from api.models.acl import AuditRoleLog
|
||||||
|
from api.models.acl import AuditTriggerLog
|
||||||
|
from api.models.acl import Permission
|
||||||
|
from api.models.acl import Resource
|
||||||
|
from api.models.acl import ResourceGroup
|
||||||
|
from api.models.acl import ResourceType
|
||||||
|
from api.models.acl import Role
|
||||||
|
from api.models.acl import RolePermission
|
||||||
|
|
||||||
|
|
||||||
class AuditScope(str, Enum):
|
class AuditScope(str, Enum):
|
||||||
|
@ -91,11 +99,8 @@ class AuditCRUD(object):
|
||||||
criterion.append(AuditPermissionLog.operate_type == v)
|
criterion.append(AuditPermissionLog.operate_type == v)
|
||||||
|
|
||||||
records = AuditPermissionLog.query.filter(
|
records = AuditPermissionLog.query.filter(
|
||||||
AuditPermissionLog.deleted == 0,
|
AuditPermissionLog.deleted == 0, *criterion).order_by(
|
||||||
*criterion) \
|
AuditPermissionLog.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
|
||||||
.order_by(AuditPermissionLog.id.desc()) \
|
|
||||||
.offset((page - 1) * page_size) \
|
|
||||||
.limit(page_size).all()
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'data': [r.to_dict() for r in records],
|
'data': [r.to_dict() for r in records],
|
||||||
|
@ -158,10 +163,8 @@ class AuditCRUD(object):
|
||||||
elif k == 'operate_type':
|
elif k == 'operate_type':
|
||||||
criterion.append(AuditRoleLog.operate_type == v)
|
criterion.append(AuditRoleLog.operate_type == v)
|
||||||
|
|
||||||
records = AuditRoleLog.query.filter(AuditRoleLog.deleted == 0, *criterion) \
|
records = AuditRoleLog.query.filter(AuditRoleLog.deleted == 0, *criterion).order_by(
|
||||||
.order_by(AuditRoleLog.id.desc()) \
|
AuditRoleLog.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
|
||||||
.offset((page - 1) * page_size) \
|
|
||||||
.limit(page_size).all()
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'data': [r.to_dict() for r in records],
|
'data': [r.to_dict() for r in records],
|
||||||
|
@ -223,11 +226,8 @@ class AuditCRUD(object):
|
||||||
criterion.append(AuditResourceLog.operate_type == v)
|
criterion.append(AuditResourceLog.operate_type == v)
|
||||||
|
|
||||||
records = AuditResourceLog.query.filter(
|
records = AuditResourceLog.query.filter(
|
||||||
AuditResourceLog.deleted == 0,
|
AuditResourceLog.deleted == 0, *criterion).order_by(
|
||||||
*criterion) \
|
AuditResourceLog.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
|
||||||
.order_by(AuditResourceLog.id.desc()) \
|
|
||||||
.offset((page - 1) * page_size) \
|
|
||||||
.limit(page_size).all()
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'data': [r.to_dict() for r in records],
|
'data': [r.to_dict() for r in records],
|
||||||
|
@ -257,11 +257,8 @@ class AuditCRUD(object):
|
||||||
criterion.append(AuditTriggerLog.operate_type == v)
|
criterion.append(AuditTriggerLog.operate_type == v)
|
||||||
|
|
||||||
records = AuditTriggerLog.query.filter(
|
records = AuditTriggerLog.query.filter(
|
||||||
AuditTriggerLog.deleted == 0,
|
AuditTriggerLog.deleted == 0, *criterion).order_by(
|
||||||
*criterion) \
|
AuditTriggerLog.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
|
||||||
.order_by(AuditTriggerLog.id.desc()) \
|
|
||||||
.offset((page - 1) * page_size) \
|
|
||||||
.limit(page_size).all()
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'data': [r.to_dict() for r in records],
|
'data': [r.to_dict() for r in records],
|
||||||
|
|
|
@ -60,15 +60,15 @@ class UserCache(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, key):
|
def get(cls, key):
|
||||||
user = cache.get(cls.PREFIX_ID.format(key)) or \
|
user = (cache.get(cls.PREFIX_ID.format(key)) or
|
||||||
cache.get(cls.PREFIX_NAME.format(key)) or \
|
cache.get(cls.PREFIX_NAME.format(key)) or
|
||||||
cache.get(cls.PREFIX_NICK.format(key)) or \
|
cache.get(cls.PREFIX_NICK.format(key)) or
|
||||||
cache.get(cls.PREFIX_WXID.format(key))
|
cache.get(cls.PREFIX_WXID.format(key)))
|
||||||
if not user:
|
if not user:
|
||||||
user = User.query.get(key) or \
|
user = (User.query.get(key) or
|
||||||
User.query.get_by_username(key) or \
|
User.query.get_by_username(key) or
|
||||||
User.query.get_by_nickname(key) or \
|
User.query.get_by_nickname(key) or
|
||||||
User.query.get_by_wxid(key)
|
User.query.get_by_wxid(key))
|
||||||
if user:
|
if user:
|
||||||
cls.set(user)
|
cls.set(user)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,9 @@ import datetime
|
||||||
from flask import abort
|
from flask import abort
|
||||||
|
|
||||||
from api.extensions import db
|
from api.extensions import db
|
||||||
from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType, AuditOperateSource
|
from api.lib.perm.acl.audit import AuditCRUD
|
||||||
|
from api.lib.perm.acl.audit import AuditOperateSource
|
||||||
|
from api.lib.perm.acl.audit import AuditOperateType
|
||||||
from api.lib.perm.acl.cache import PermissionCache
|
from api.lib.perm.acl.cache import PermissionCache
|
||||||
from api.lib.perm.acl.cache import RoleCache
|
from api.lib.perm.acl.cache import RoleCache
|
||||||
from api.lib.perm.acl.cache import UserCache
|
from api.lib.perm.acl.cache import UserCache
|
||||||
|
@ -97,8 +99,8 @@ class PermissionCRUD(object):
|
||||||
elif group_id is not None:
|
elif group_id is not None:
|
||||||
from api.models.acl import ResourceGroup
|
from api.models.acl import ResourceGroup
|
||||||
|
|
||||||
group = ResourceGroup.get_by_id(group_id) or \
|
group = ResourceGroup.get_by_id(group_id) or abort(
|
||||||
abort(404, ErrFormat.resource_group_not_found.format("id={}".format(group_id)))
|
404, ErrFormat.resource_group_not_found.format("id={}".format(group_id)))
|
||||||
app_id = group.app_id
|
app_id = group.app_id
|
||||||
rt_id = group.resource_type_id
|
rt_id = group.resource_type_id
|
||||||
if not perms:
|
if not perms:
|
||||||
|
@ -206,8 +208,8 @@ class PermissionCRUD(object):
|
||||||
if resource_id is not None:
|
if resource_id is not None:
|
||||||
from api.models.acl import Resource
|
from api.models.acl import Resource
|
||||||
|
|
||||||
resource = Resource.get_by_id(resource_id) or \
|
resource = Resource.get_by_id(resource_id) or abort(
|
||||||
abort(404, ErrFormat.resource_not_found.format("id={}".format(resource_id)))
|
404, ErrFormat.resource_not_found.format("id={}".format(resource_id)))
|
||||||
app_id = resource.app_id
|
app_id = resource.app_id
|
||||||
rt_id = resource.resource_type_id
|
rt_id = resource.resource_type_id
|
||||||
if not perms:
|
if not perms:
|
||||||
|
@ -216,8 +218,8 @@ class PermissionCRUD(object):
|
||||||
elif group_id is not None:
|
elif group_id is not None:
|
||||||
from api.models.acl import ResourceGroup
|
from api.models.acl import ResourceGroup
|
||||||
|
|
||||||
group = ResourceGroup.get_by_id(group_id) or \
|
group = ResourceGroup.get_by_id(group_id) or abort(
|
||||||
abort(404, ErrFormat.resource_group_not_found.format("id={}".format(group_id)))
|
404, ErrFormat.resource_group_not_found.format("id={}".format(group_id)))
|
||||||
app_id = group.app_id
|
app_id = group.app_id
|
||||||
|
|
||||||
rt_id = group.resource_type_id
|
rt_id = group.resource_type_id
|
||||||
|
|
|
@ -5,7 +5,9 @@ from flask import abort
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
from api.extensions import db
|
from api.extensions import db
|
||||||
from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType, AuditScope
|
from api.lib.perm.acl.audit import AuditCRUD
|
||||||
|
from api.lib.perm.acl.audit import AuditOperateType
|
||||||
|
from api.lib.perm.acl.audit import AuditScope
|
||||||
from api.lib.perm.acl.cache import ResourceCache
|
from api.lib.perm.acl.cache import ResourceCache
|
||||||
from api.lib.perm.acl.cache import ResourceGroupCache
|
from api.lib.perm.acl.cache import ResourceGroupCache
|
||||||
from api.lib.perm.acl.cache import UserCache
|
from api.lib.perm.acl.cache import UserCache
|
||||||
|
@ -102,8 +104,8 @@ class ResourceTypeCRUD(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete(cls, rt_id):
|
def delete(cls, rt_id):
|
||||||
rt = ResourceType.get_by_id(rt_id) or \
|
rt = ResourceType.get_by_id(rt_id) or abort(
|
||||||
abort(404, ErrFormat.resource_type_not_found.format("id={}".format(rt_id)))
|
404, ErrFormat.resource_type_not_found.format("id={}".format(rt_id)))
|
||||||
|
|
||||||
Resource.get_by(resource_type_id=rt_id) and abort(400, ErrFormat.resource_type_cannot_delete)
|
Resource.get_by(resource_type_id=rt_id) and abort(400, ErrFormat.resource_type_cannot_delete)
|
||||||
|
|
||||||
|
@ -165,8 +167,8 @@ class ResourceGroupCRUD(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add(name, type_id, app_id, uid=None):
|
def add(name, type_id, app_id, uid=None):
|
||||||
ResourceGroup.get_by(name=name, resource_type_id=type_id, app_id=app_id) and \
|
ResourceGroup.get_by(name=name, resource_type_id=type_id, app_id=app_id) and abort(
|
||||||
abort(400, ErrFormat.resource_group_exists.format(name))
|
400, ErrFormat.resource_group_exists.format(name))
|
||||||
rg = ResourceGroup.create(name=name, resource_type_id=type_id, app_id=app_id, uid=uid)
|
rg = ResourceGroup.create(name=name, resource_type_id=type_id, app_id=app_id, uid=uid)
|
||||||
|
|
||||||
AuditCRUD.add_resource_log(app_id, AuditOperateType.create,
|
AuditCRUD.add_resource_log(app_id, AuditOperateType.create,
|
||||||
|
@ -175,8 +177,8 @@ class ResourceGroupCRUD(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update(rg_id, items):
|
def update(rg_id, items):
|
||||||
rg = ResourceGroup.get_by_id(rg_id) or \
|
rg = ResourceGroup.get_by_id(rg_id) or abort(
|
||||||
abort(404, ErrFormat.resource_group_not_found.format("id={}".format(rg_id)))
|
404, ErrFormat.resource_group_not_found.format("id={}".format(rg_id)))
|
||||||
|
|
||||||
existed = ResourceGroupItems.get_by(group_id=rg_id, to_dict=False)
|
existed = ResourceGroupItems.get_by(group_id=rg_id, to_dict=False)
|
||||||
existed_ids = [i.resource_id for i in existed]
|
existed_ids = [i.resource_id for i in existed]
|
||||||
|
@ -196,8 +198,8 @@ class ResourceGroupCRUD(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete(rg_id):
|
def delete(rg_id):
|
||||||
rg = ResourceGroup.get_by_id(rg_id) or \
|
rg = ResourceGroup.get_by_id(rg_id) or abort(
|
||||||
abort(404, ErrFormat.resource_group_not_found.format("id={}".format(rg_id)))
|
404, ErrFormat.resource_group_not_found.format("id={}".format(rg_id)))
|
||||||
|
|
||||||
origin = rg.to_dict()
|
origin = rg.to_dict()
|
||||||
rg.soft_delete()
|
rg.soft_delete()
|
||||||
|
@ -266,8 +268,8 @@ class ResourceCRUD(object):
|
||||||
def add(cls, name, type_id, app_id, uid=None):
|
def add(cls, name, type_id, app_id, uid=None):
|
||||||
type_id = cls._parse_resource_type_id(type_id, app_id)
|
type_id = cls._parse_resource_type_id(type_id, app_id)
|
||||||
|
|
||||||
Resource.get_by(name=name, resource_type_id=type_id, app_id=app_id) and \
|
Resource.get_by(name=name, resource_type_id=type_id, app_id=app_id) and abort(
|
||||||
abort(400, ErrFormat.resource_exists.format(name))
|
400, ErrFormat.resource_exists.format(name))
|
||||||
|
|
||||||
r = Resource.create(name=name, resource_type_id=type_id, app_id=app_id, uid=uid)
|
r = Resource.create(name=name, resource_type_id=type_id, app_id=app_id, uid=uid)
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,9 @@ from sqlalchemy import or_
|
||||||
|
|
||||||
from api.extensions import db
|
from api.extensions import db
|
||||||
from api.lib.perm.acl.app import AppCRUD
|
from api.lib.perm.acl.app import AppCRUD
|
||||||
from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType, AuditScope
|
from api.lib.perm.acl.audit import AuditCRUD
|
||||||
|
from api.lib.perm.acl.audit import AuditOperateType
|
||||||
|
from api.lib.perm.acl.audit import AuditScope
|
||||||
from api.lib.perm.acl.cache import AppCache
|
from api.lib.perm.acl.cache import AppCache
|
||||||
from api.lib.perm.acl.cache import HasResourceRoleCache
|
from api.lib.perm.acl.cache import HasResourceRoleCache
|
||||||
from api.lib.perm.acl.cache import RoleCache
|
from api.lib.perm.acl.cache import RoleCache
|
||||||
|
@ -69,16 +71,16 @@ class RoleRelationCRUD(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_parent_ids(rid, app_id):
|
def get_parent_ids(rid, app_id):
|
||||||
if app_id is not None:
|
if app_id is not None:
|
||||||
return [i.parent_id for i in RoleRelation.get_by(child_id=rid, app_id=app_id, to_dict=False)] + \
|
return ([i.parent_id for i in RoleRelation.get_by(child_id=rid, app_id=app_id, to_dict=False)] +
|
||||||
[i.parent_id for i in RoleRelation.get_by(child_id=rid, app_id=None, to_dict=False)]
|
[i.parent_id for i in RoleRelation.get_by(child_id=rid, app_id=None, to_dict=False)])
|
||||||
else:
|
else:
|
||||||
return [i.parent_id for i in RoleRelation.get_by(child_id=rid, app_id=app_id, to_dict=False)]
|
return [i.parent_id for i in RoleRelation.get_by(child_id=rid, app_id=app_id, to_dict=False)]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_child_ids(rid, app_id):
|
def get_child_ids(rid, app_id):
|
||||||
if app_id is not None:
|
if app_id is not None:
|
||||||
return [i.child_id for i in RoleRelation.get_by(parent_id=rid, app_id=app_id, to_dict=False)] + \
|
return ([i.child_id for i in RoleRelation.get_by(parent_id=rid, app_id=app_id, to_dict=False)] +
|
||||||
[i.child_id for i in RoleRelation.get_by(parent_id=rid, app_id=None, to_dict=False)]
|
[i.child_id for i in RoleRelation.get_by(parent_id=rid, app_id=None, to_dict=False)])
|
||||||
else:
|
else:
|
||||||
return [i.child_id for i in RoleRelation.get_by(parent_id=rid, app_id=app_id, to_dict=False)]
|
return [i.child_id for i in RoleRelation.get_by(parent_id=rid, app_id=app_id, to_dict=False)]
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,10 @@ import json
|
||||||
import re
|
import re
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
|
|
||||||
from flask import abort, current_app
|
from flask import abort
|
||||||
|
|
||||||
from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType
|
from api.lib.perm.acl.audit import AuditCRUD
|
||||||
|
from api.lib.perm.acl.audit import AuditOperateType
|
||||||
from api.lib.perm.acl.cache import UserCache
|
from api.lib.perm.acl.cache import UserCache
|
||||||
from api.lib.perm.acl.const import ACL_QUEUE
|
from api.lib.perm.acl.const import ACL_QUEUE
|
||||||
from api.lib.perm.acl.resp_format import ErrFormat
|
from api.lib.perm.acl.resp_format import ErrFormat
|
||||||
|
|
|
@ -9,7 +9,9 @@ from flask import abort
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
from api.extensions import db
|
from api.extensions import db
|
||||||
from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType, AuditScope
|
from api.lib.perm.acl.audit import AuditCRUD
|
||||||
|
from api.lib.perm.acl.audit import AuditOperateType
|
||||||
|
from api.lib.perm.acl.audit import AuditScope
|
||||||
from api.lib.perm.acl.cache import UserCache
|
from api.lib.perm.acl.cache import UserCache
|
||||||
from api.lib.perm.acl.resp_format import ErrFormat
|
from api.lib.perm.acl.resp_format import ErrFormat
|
||||||
from api.lib.perm.acl.role import RoleCRUD
|
from api.lib.perm.acl.role import RoleCRUD
|
||||||
|
@ -49,11 +51,9 @@ class UserCRUD(object):
|
||||||
kwargs['block'] = 0
|
kwargs['block'] = 0
|
||||||
kwargs['key'], kwargs['secret'] = cls.gen_key_secret()
|
kwargs['key'], kwargs['secret'] = cls.gen_key_secret()
|
||||||
|
|
||||||
user_employee = db.session.query(User).filter(User.deleted.is_(False)).order_by(
|
user_employee = db.session.query(User).filter(User.deleted.is_(False)).order_by(User.employee_id.desc()).first()
|
||||||
User.employee_id.desc()).first()
|
|
||||||
|
|
||||||
biggest_employee_id = int(float(user_employee.employee_id)) \
|
biggest_employee_id = int(float(user_employee.employee_id)) if user_employee is not None else 0
|
||||||
if user_employee is not None else 0
|
|
||||||
|
|
||||||
kwargs['employee_id'] = '{0:04d}'.format(biggest_employee_id + 1)
|
kwargs['employee_id'] = '{0:04d}'.format(biggest_employee_id + 1)
|
||||||
user = User.create(**kwargs)
|
user = User.create(**kwargs)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import json
|
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from typing import Set
|
from typing import Set
|
||||||
|
@ -113,7 +112,7 @@ class RedisHandler(object):
|
||||||
try:
|
try:
|
||||||
ret = self.r.hdel(prefix, key_id)
|
ret = self.r.hdel(prefix, key_id)
|
||||||
if not ret:
|
if not ret:
|
||||||
current_app.logger.warn("[{0}] is not in redis".format(key_id))
|
current_app.logger.warning("[{0}] is not in redis".format(key_id))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
current_app.logger.error("delete redis key error, {0}".format(str(e)))
|
current_app.logger.error("delete redis key error, {0}".format(str(e)))
|
||||||
|
|
||||||
|
@ -204,9 +203,9 @@ class ESHandler(object):
|
||||||
|
|
||||||
res = self.es.search(index=self.index, body=query, filter_path=filter_path)
|
res = self.es.search(index=self.index, body=query, filter_path=filter_path)
|
||||||
if res['hits'].get('hits'):
|
if res['hits'].get('hits'):
|
||||||
return res['hits']['total']['value'], \
|
return (res['hits']['total']['value'],
|
||||||
[i['_source'] for i in res['hits']['hits']], \
|
[i['_source'] for i in res['hits']['hits']],
|
||||||
res.get("aggregations", {})
|
res.get("aggregations", {}))
|
||||||
else:
|
else:
|
||||||
return 0, [], {}
|
return 0, [], {}
|
||||||
|
|
||||||
|
@ -257,93 +256,10 @@ class Lock(object):
|
||||||
self.release()
|
self.release()
|
||||||
|
|
||||||
|
|
||||||
class Redis2Handler(object):
|
|
||||||
def __init__(self, flask_app=None, prefix=None):
|
|
||||||
self.flask_app = flask_app
|
|
||||||
self.prefix = prefix
|
|
||||||
self.r = None
|
|
||||||
|
|
||||||
def init_app(self, app):
|
|
||||||
self.flask_app = app
|
|
||||||
config = self.flask_app.config
|
|
||||||
try:
|
|
||||||
pool = redis.ConnectionPool(
|
|
||||||
max_connections=config.get("REDIS_MAX_CONN"),
|
|
||||||
host=config.get("ONEAGENT_REDIS_HOST"),
|
|
||||||
port=config.get("ONEAGENT_REDIS_PORT"),
|
|
||||||
db=config.get("ONEAGENT_REDIS_DB"),
|
|
||||||
password=config.get("ONEAGENT_REDIS_PASSWORD")
|
|
||||||
)
|
|
||||||
self.r = redis.Redis(connection_pool=pool)
|
|
||||||
except Exception as e:
|
|
||||||
current_app.logger.warning(str(e))
|
|
||||||
current_app.logger.error("init redis connection failed")
|
|
||||||
|
|
||||||
def get(self, key):
|
|
||||||
try:
|
|
||||||
value = json.loads(self.r.get(key))
|
|
||||||
except:
|
|
||||||
return
|
|
||||||
|
|
||||||
return value
|
|
||||||
|
|
||||||
def lrange(self, key, start=0, end=-1):
|
|
||||||
try:
|
|
||||||
value = "".join(map(redis_decode, self.r.lrange(key, start, end) or []))
|
|
||||||
except:
|
|
||||||
return
|
|
||||||
|
|
||||||
return value
|
|
||||||
|
|
||||||
def lrange2(self, key, start=0, end=-1):
|
|
||||||
try:
|
|
||||||
return list(map(redis_decode, self.r.lrange(key, start, end) or []))
|
|
||||||
except:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def llen(self, key):
|
|
||||||
try:
|
|
||||||
return self.r.llen(key) or 0
|
|
||||||
except:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def hget(self, key, field):
|
|
||||||
try:
|
|
||||||
return self.r.hget(key, field)
|
|
||||||
except Exception as e:
|
|
||||||
current_app.logger.warning("hget redis failed, %s" % str(e))
|
|
||||||
return
|
|
||||||
|
|
||||||
def hset(self, key, field, value):
|
|
||||||
try:
|
|
||||||
self.r.hset(key, field, value)
|
|
||||||
except Exception as e:
|
|
||||||
current_app.logger.warning("hset redis failed, %s" % str(e))
|
|
||||||
return
|
|
||||||
|
|
||||||
def expire(self, key, timeout):
|
|
||||||
try:
|
|
||||||
self.r.expire(key, timeout)
|
|
||||||
except Exception as e:
|
|
||||||
current_app.logger.warning("expire redis failed, %s" % str(e))
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def redis_decode(x):
|
|
||||||
try:
|
|
||||||
return x.decode()
|
|
||||||
except Exception as e:
|
|
||||||
print(x, e)
|
|
||||||
try:
|
|
||||||
return x.decode("gb18030")
|
|
||||||
except:
|
|
||||||
return "decode failed"
|
|
||||||
|
|
||||||
|
|
||||||
class AESCrypto(object):
|
class AESCrypto(object):
|
||||||
BLOCK_SIZE = 16 # Bytes
|
BLOCK_SIZE = 16 # Bytes
|
||||||
pad = lambda s: s + (AESCrypto.BLOCK_SIZE - len(s) % AESCrypto.BLOCK_SIZE) * \
|
pad = lambda s: s + ((AESCrypto.BLOCK_SIZE - len(s) % AESCrypto.BLOCK_SIZE) *
|
||||||
chr(AESCrypto.BLOCK_SIZE - len(s) % AESCrypto.BLOCK_SIZE)
|
chr(AESCrypto.BLOCK_SIZE - len(s) % AESCrypto.BLOCK_SIZE))
|
||||||
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
|
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
|
||||||
|
|
||||||
iv = '0102030405060708'
|
iv = '0102030405060708'
|
||||||
|
@ -352,7 +268,7 @@ class AESCrypto(object):
|
||||||
def key():
|
def key():
|
||||||
key = current_app.config.get("SECRET_KEY")[:16]
|
key = current_app.config.get("SECRET_KEY")[:16]
|
||||||
if len(key) < 16:
|
if len(key) < 16:
|
||||||
key = "{}{}".format(key, (16 - len(key) * "x"))
|
key = "{}{}".format(key, (16 - len(key)) * "x")
|
||||||
|
|
||||||
return key.encode('utf8')
|
return key.encode('utf8')
|
||||||
|
|
||||||
|
|
|
@ -80,3 +80,10 @@ class InternalMessage(Model):
|
||||||
category = db.Column(db.VARCHAR(128), nullable=False)
|
category = db.Column(db.VARCHAR(128), nullable=False)
|
||||||
message_data = db.Column(db.JSON, nullable=True)
|
message_data = db.Column(db.JSON, nullable=True)
|
||||||
employee_id = db.Column(db.Integer, db.ForeignKey('common_employee.employee_id'), comment='ID')
|
employee_id = db.Column(db.Integer, db.ForeignKey('common_employee.employee_id'), comment='ID')
|
||||||
|
|
||||||
|
|
||||||
|
class CommonData(Model):
|
||||||
|
__table_name__ = 'common_data'
|
||||||
|
|
||||||
|
data_type = db.Column(db.VARCHAR(255), default='')
|
||||||
|
data = db.Column(db.JSON)
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from inspect import getmembers, isclass
|
from inspect import getmembers
|
||||||
|
from inspect import isclass
|
||||||
|
|
||||||
import six
|
import six
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
|
|
|
@ -5,17 +5,20 @@ import re
|
||||||
|
|
||||||
from celery_once import QueueOnce
|
from celery_once import QueueOnce
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from werkzeug.exceptions import BadRequest, NotFound
|
from werkzeug.exceptions import BadRequest
|
||||||
|
from werkzeug.exceptions import NotFound
|
||||||
|
|
||||||
from api.extensions import celery
|
from api.extensions import celery
|
||||||
from api.extensions import db
|
from api.extensions import db
|
||||||
|
from api.lib.perm.acl.audit import AuditCRUD
|
||||||
|
from api.lib.perm.acl.audit import AuditOperateSource
|
||||||
|
from api.lib.perm.acl.audit import AuditOperateType
|
||||||
from api.lib.perm.acl.cache import AppCache
|
from api.lib.perm.acl.cache import AppCache
|
||||||
from api.lib.perm.acl.cache import RoleCache
|
from api.lib.perm.acl.cache import RoleCache
|
||||||
from api.lib.perm.acl.cache import RoleRelationCache
|
from api.lib.perm.acl.cache import RoleRelationCache
|
||||||
from api.lib.perm.acl.cache import UserCache
|
from api.lib.perm.acl.cache import UserCache
|
||||||
from api.lib.perm.acl.const import ACL_QUEUE
|
from api.lib.perm.acl.const import ACL_QUEUE
|
||||||
from api.lib.perm.acl.record import OperateRecordCRUD
|
from api.lib.perm.acl.record import OperateRecordCRUD
|
||||||
from api.lib.perm.acl.audit import AuditCRUD, AuditOperateType, AuditOperateSource
|
|
||||||
from api.models.acl import Resource
|
from api.models.acl import Resource
|
||||||
from api.models.acl import Role
|
from api.models.acl import Role
|
||||||
from api.models.acl import Trigger
|
from api.models.acl import Trigger
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import six
|
|
||||||
import jwt
|
import jwt
|
||||||
|
import six
|
||||||
from flask import abort
|
from flask import abort
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from flask import request
|
from flask import request
|
||||||
from flask_login import login_user, logout_user
|
from flask_login import login_user
|
||||||
|
from flask_login import logout_user
|
||||||
|
|
||||||
from api.lib.decorator import args_required
|
from api.lib.decorator import args_required
|
||||||
from api.lib.perm.acl.cache import User
|
from api.lib.perm.acl.cache import User
|
||||||
|
|
|
@ -11,7 +11,8 @@ from api.lib.cmdb.cache import CITypeCache
|
||||||
from api.lib.cmdb.ci import CIManager
|
from api.lib.cmdb.ci import CIManager
|
||||||
from api.lib.cmdb.ci import CIRelationManager
|
from api.lib.cmdb.ci import CIRelationManager
|
||||||
from api.lib.cmdb.const import ExistPolicy
|
from api.lib.cmdb.const import ExistPolicy
|
||||||
from api.lib.cmdb.const import ResourceTypeEnum, PermEnum
|
from api.lib.cmdb.const import PermEnum
|
||||||
|
from api.lib.cmdb.const import ResourceTypeEnum
|
||||||
from api.lib.cmdb.const import RetKey
|
from api.lib.cmdb.const import RetKey
|
||||||
from api.lib.cmdb.perms import has_perm_for_ci
|
from api.lib.cmdb.perms import has_perm_for_ci
|
||||||
from api.lib.cmdb.search import SearchError
|
from api.lib.cmdb.search import SearchError
|
||||||
|
|
|
@ -6,7 +6,9 @@ from flask import request
|
||||||
|
|
||||||
from api.lib.cmdb.ci_type import CITypeManager
|
from api.lib.cmdb.ci_type import CITypeManager
|
||||||
from api.lib.cmdb.ci_type import CITypeRelationManager
|
from api.lib.cmdb.ci_type import CITypeRelationManager
|
||||||
from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum
|
from api.lib.cmdb.const import PermEnum
|
||||||
|
from api.lib.cmdb.const import ResourceTypeEnum
|
||||||
|
from api.lib.cmdb.const import RoleEnum
|
||||||
from api.lib.cmdb.resp_format import ErrFormat
|
from api.lib.cmdb.resp_format import ErrFormat
|
||||||
from api.lib.decorator import args_required
|
from api.lib.decorator import args_required
|
||||||
from api.lib.perm.acl.acl import ACLManager
|
from api.lib.perm.acl.acl import ACLManager
|
||||||
|
|
|
@ -7,7 +7,8 @@ from flask import abort
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from api.lib.cmdb.ci import CIManager
|
from api.lib.cmdb.ci import CIManager
|
||||||
from api.lib.cmdb.const import ResourceTypeEnum, PermEnum
|
from api.lib.cmdb.const import PermEnum
|
||||||
|
from api.lib.cmdb.const import ResourceTypeEnum
|
||||||
from api.lib.cmdb.const import RoleEnum
|
from api.lib.cmdb.const import RoleEnum
|
||||||
from api.lib.cmdb.history import AttributeHistoryManger
|
from api.lib.cmdb.history import AttributeHistoryManger
|
||||||
from api.lib.cmdb.history import CITypeHistoryManager
|
from api.lib.cmdb.history import CITypeHistoryManager
|
||||||
|
|
|
@ -5,7 +5,9 @@ from flask import abort
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from api.lib.cmdb.ci_type import CITypeManager
|
from api.lib.cmdb.ci_type import CITypeManager
|
||||||
from api.lib.cmdb.const import PermEnum, ResourceTypeEnum, RoleEnum
|
from api.lib.cmdb.const import PermEnum
|
||||||
|
from api.lib.cmdb.const import ResourceTypeEnum
|
||||||
|
from api.lib.cmdb.const import RoleEnum
|
||||||
from api.lib.cmdb.perms import CIFilterPermsCRUD
|
from api.lib.cmdb.perms import CIFilterPermsCRUD
|
||||||
from api.lib.cmdb.preference import PreferenceManager
|
from api.lib.cmdb.preference import PreferenceManager
|
||||||
from api.lib.cmdb.resp_format import ErrFormat
|
from api.lib.cmdb.resp_format import ErrFormat
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
from flask import request
|
||||||
|
|
||||||
|
from api.lib.common_setting.common_data import CommonDataCRUD
|
||||||
|
from api.resource import APIView
|
||||||
|
|
||||||
|
prefix = '/data'
|
||||||
|
|
||||||
|
|
||||||
|
class DataView(APIView):
|
||||||
|
url_prefix = (f'{prefix}/<string:data_type>',)
|
||||||
|
|
||||||
|
def get(self, data_type):
|
||||||
|
data_list = CommonDataCRUD.get_data_by_type(data_type)
|
||||||
|
|
||||||
|
return self.jsonify(data_list)
|
||||||
|
|
||||||
|
def post(self, data_type):
|
||||||
|
params = request.json
|
||||||
|
CommonDataCRUD.create_new_data(data_type, **params)
|
||||||
|
|
||||||
|
return self.jsonify(params)
|
||||||
|
|
||||||
|
|
||||||
|
class DataViewWithId(APIView):
|
||||||
|
url_prefix = (f'{prefix}/<string:data_type>/<int:_id>',)
|
||||||
|
|
||||||
|
def put(self, data_type, _id):
|
||||||
|
params = request.json
|
||||||
|
res = CommonDataCRUD.update_data(_id, **params)
|
||||||
|
|
||||||
|
return self.jsonify(res.to_dict())
|
||||||
|
|
||||||
|
def delete(self, data_type, _id):
|
||||||
|
CommonDataCRUD.delete(_id)
|
||||||
|
return self.jsonify({})
|
|
@ -6,7 +6,9 @@ from flask import Blueprint
|
||||||
from flask_restful import Api
|
from flask_restful import Api
|
||||||
|
|
||||||
from api.resource import register_resources
|
from api.resource import register_resources
|
||||||
from .account import LoginView, LogoutView, AuthWithKeyView
|
from .account import AuthWithKeyView
|
||||||
|
from .account import LoginView
|
||||||
|
from .account import LogoutView
|
||||||
|
|
||||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue