acl done and bugfix

This commit is contained in:
pycook 2019-12-06 22:33:31 +08:00
parent 6973cc68ed
commit 5669e253a9
20 changed files with 267 additions and 135 deletions

View File

@ -6,15 +6,27 @@ import json
import click
from flask import current_app
from flask.cli import with_appcontext
from werkzeug.exceptions import BadRequest
import api.lib.cmdb.ci
from api.extensions import db
from api.extensions import rd
from api.lib.cmdb.const import PermEnum
from api.lib.cmdb.const import REDIS_PREFIX_CI
from api.lib.cmdb.const import REDIS_PREFIX_CI_RELATION
from api.lib.cmdb.const import ResourceTypeEnum
from api.lib.cmdb.const import RoleEnum
from api.lib.cmdb.const import ValueTypeEnum
from api.lib.perm.acl.acl import ACLManager
from api.lib.perm.acl.cache import AppCache
from api.lib.perm.acl.resource import ResourceCRUD
from api.lib.perm.acl.resource import ResourceTypeCRUD
from api.lib.perm.acl.role import RoleCRUD
from api.models.acl import ResourceType
from api.models.cmdb import CI
from api.models.cmdb import CIRelation
from api.models.cmdb import CIType
from api.models.cmdb import PreferenceRelationView
@click.command()
@ -74,3 +86,52 @@ def init_cache():
rd.create_or_update(relations, REDIS_PREFIX_CI_RELATION)
db.session.remove()
@click.command()
@with_appcontext
def init_acl():
app_id = AppCache.get('cmdb').id
# 1. add resource type
for resource_type in ResourceTypeEnum.all():
try:
ResourceTypeCRUD.add(app_id, resource_type, '', PermEnum.all())
except BadRequest:
pass
# 2. add role
try:
RoleCRUD.add_role(RoleEnum.CONFIG, app_id, True)
except BadRequest:
pass
try:
RoleCRUD.add_role(RoleEnum.CMDB_READ_ALL, app_id, False)
except BadRequest:
pass
# 3. add resource and grant
ci_types = CIType.get_by(to_dict=False)
type_id = ResourceType.get_by(name=ResourceTypeEnum.CI, first=True, to_dict=False).id
for ci_type in ci_types:
try:
ResourceCRUD.add(ci_type.name, type_id, app_id)
except BadRequest:
pass
ACLManager().grant_resource_to_role(ci_type.name,
RoleEnum.CMDB_READ_ALL,
ResourceTypeEnum.CI,
[PermEnum.READ])
relation_views = PreferenceRelationView.get_by(to_dict=False)
type_id = ResourceType.get_by(name=ResourceTypeEnum.RELATION_VIEW, first=True, to_dict=False).id
for view in relation_views:
try:
ResourceCRUD.add(view.name, type_id, app_id)
except BadRequest:
pass
ACLManager().grant_resource_to_role(view.name,
RoleEnum.CMDB_READ_ALL,
ResourceTypeEnum.RELATION_VIEW,
[PermEnum.READ])

View File

@ -12,7 +12,6 @@ from api.extensions import db
from api.extensions import rd
from api.lib.cmdb.cache import AttributeCache
from api.lib.cmdb.cache import CITypeCache
from api.lib.cmdb.cache import RelationTypeCache
from api.lib.cmdb.ci_type import CITypeAttributeManager
from api.lib.cmdb.ci_type import CITypeManager
from api.lib.cmdb.const import CMDB_QUEUE
@ -32,6 +31,7 @@ from api.lib.utils import handle_arg_list
from api.models.cmdb import CI
from api.models.cmdb import CIRelation
from api.models.cmdb import CITypeAttribute
from api.models.cmdb import CITypeRelation
from api.tasks.cmdb import ci_cache
from api.tasks.cmdb import ci_delete
from api.tasks.cmdb import ci_relation_cache
@ -52,7 +52,7 @@ class CIManager(object):
@staticmethod
def confirm_ci_existed(ci_id):
CI.get_by_id(ci_id) or abort(404, "CI <{0}> is not existed".format(ci_id))
return CI.get_by_id(ci_id) or abort(404, "CI <{0}> is not existed".format(ci_id))
@classmethod
def get_ci_by_id(cls, ci_id, ret_key=RetKey.NAME, fields=None, need_children=True):
@ -408,10 +408,6 @@ class CIRelationManager(object):
def __init__(self):
pass
@staticmethod
def _get_default_relation_type():
return RelationTypeCache.get("contain").id # FIXME
@classmethod
def get_children(cls, ci_id, ret_key=RetKey.NAME):
second_cis = CIRelation.get_by(first_ci_id=ci_id, to_dict=False)
@ -428,7 +424,8 @@ class CIRelationManager(object):
res[ci_type.name] = children
return res
def get_second_cis(self, first_ci_id, relation_type_id=None, page=1, per_page=None, **kwargs):
@staticmethod
def get_second_cis(first_ci_id, relation_type_id=None, page=1, per_page=None):
second_cis = db.session.query(CI.id).filter(CI.deleted.is_(False)).join(
CIRelation, CIRelation.second_ci_id == CI.id).filter(
CIRelation.first_ci_id == first_ci_id).filter(CIRelation.deleted.is_(False))
@ -436,9 +433,6 @@ class CIRelationManager(object):
if relation_type_id is not None:
second_cis = second_cis.filter(CIRelation.relation_type_id == relation_type_id)
if kwargs: # TODO: special for devices
second_cis = self._query_wrap_for_device(second_cis, **kwargs)
numfound = second_cis.count()
if per_page != "all":
second_cis = second_cis.offset((page - 1) * per_page).limit(per_page).all()
@ -473,33 +467,6 @@ class CIRelationManager(object):
return query_sql
def _query_wrap_for_device(self, query_sql, **kwargs):
_type = kwargs.pop("_type", False) or kwargs.pop("type", False) or kwargs.pop("ci_type", False)
if _type:
ci_type = CITypeCache.get(_type)
if ci_type is None:
return
query_sql = query_sql.filter(CI.type_id == ci_type.id)
for k, v in kwargs.items():
attr = AttributeCache.get(k)
if attr is None:
continue
value_table = TableMap(attr_name=k).table
ci_table = query_sql.subquery()
query_sql = db.session.query(ci_table.c.id).join(
value_table, value_table.ci_id == ci_table.c.id).filter(
value_table.attr_id == attr.id).filter(ci_table.deleted.is_(False)).filter(
value_table.value.ilike(v.replace("*", "%")))
# current_app.logger.debug(query_sql)
sort_by = kwargs.pop("sort", "")
if sort_by:
query_sql = self._sort_handler(sort_by, query_sql)
return query_sql
@classmethod
def get_first_cis(cls, second_ci, relation_type_id=None, page=1, per_page=None):
first_cis = db.session.query(CIRelation.first_ci_id).filter(
@ -519,10 +486,8 @@ class CIRelationManager(object):
@classmethod
def add(cls, first_ci_id, second_ci_id, more=None, relation_type_id=None):
relation_type_id = relation_type_id or cls._get_default_relation_type()
CIManager.confirm_ci_existed(first_ci_id)
CIManager.confirm_ci_existed(second_ci_id)
first_ci = CIManager.confirm_ci_existed(first_ci_id)
second_ci = CIManager.confirm_ci_existed(second_ci_id)
existed = CIRelation.get_by(first_ci_id=first_ci_id,
second_ci_id=second_ci_id,
@ -531,11 +496,22 @@ class CIRelationManager(object):
if existed is not None:
if existed.relation_type_id != relation_type_id:
existed.update(relation_type_id=relation_type_id)
CIRelationHistoryManager().add(existed, OperateType.UPDATE)
else:
if relation_type_id is None:
type_relation = CITypeRelation.get_by(parent_id=first_ci.type_id,
child_id=second_ci.type_id,
first=True,
to_dict=False)
relation_type_id = type_relation and type_relation.relation_type_id
relation_type_id or abort(404, "Relation {0} <-> {1} is not found".format(
first_ci.ci_type.name, second_ci.ci_type.name))
existed = CIRelation.create(first_ci_id=first_ci_id,
second_ci_id=second_ci_id,
relation_type_id=relation_type_id)
CIRelationHistoryManager().add(existed, OperateType.ADD)
ci_relation_cache.apply_async(args=(first_ci_id, second_ci_id), queue=CMDB_QUEUE)

View File

@ -69,6 +69,15 @@ class CITypeManager(object):
CITypeCache.clean(ci_type.name)
if current_app.config.get("USE_ACL"):
from api.lib.perm.acl.acl import ACLManager
from api.lib.cmdb.const import ResourceTypeEnum, RoleEnum, PermEnum
ACLManager().add_resource(ci_type.name, ResourceTypeEnum.CI)
ACLManager().grant_resource_to_role(ci_type.name,
RoleEnum.CMDB_READ_ALL,
ResourceTypeEnum.CI,
permissions=[PermEnum.READ])
return ci_type.id
@classmethod

View File

@ -37,8 +37,9 @@ class RetKey(BaseEnum):
ALIAS = "alias"
class ResourceType(BaseEnum):
class ResourceTypeEnum(BaseEnum):
CI = "CIType"
RELATION_VIEW = "RelationView"
class PermEnum(BaseEnum):
@ -50,6 +51,7 @@ class PermEnum(BaseEnum):
class RoleEnum(BaseEnum):
CONFIG = "admin"
CMDB_READ_ALL = "CMDB_READ_ALL"
CMDB_QUEUE = "cmdb_async"

View File

@ -7,6 +7,7 @@ import json
import six
import toposort
from flask import abort
from flask import current_app
from flask import g
from api.extensions import db
@ -19,6 +20,8 @@ from api.models.cmdb import CITypeRelation
from api.models.cmdb import PreferenceRelationView
from api.models.cmdb import PreferenceShowAttributes
from api.models.cmdb import PreferenceTreeView
from api.lib.perm.acl.acl import ACLManager
from api.lib.cmdb.const import ResourceTypeEnum, RoleEnum, PermEnum
class PreferenceManager(object):
@ -116,6 +119,11 @@ class PreferenceManager(object):
@staticmethod
def get_relation_view():
views = PreferenceRelationView.get_by(to_dict=True)
if current_app.config.get("USE_ACL"):
views = [i for i in views if ACLManager().has_permission(i.get('name'),
ResourceTypeEnum.RELATION_VIEW,
PermEnum.READ)]
view2cr_ids = dict()
result = dict()
name2id = list()
@ -170,6 +178,13 @@ class PreferenceManager(object):
if existed is None:
PreferenceRelationView.create(name=name, cr_ids=json.dumps(cr_ids))
if current_app.config.get("USE_ACL"):
ACLManager().add_resource(name, ResourceTypeEnum.RELATION_VIEW)
ACLManager().grant_resource_to_role(name,
RoleEnum.CMDB_READ_ALL,
ResourceTypeEnum.RELATION_VIEW,
permissions=[PermEnum.READ])
return cls.get_relation_view()
@staticmethod

View File

@ -6,54 +6,83 @@ import six
from flask import current_app, g, request
from flask import session, abort
from api.lib.cmdb.const import ResourceTypeEnum as CmdbResourceType
from api.lib.cmdb.const import RoleEnum
from api.lib.perm.acl.cache import AppCache
from api.models.acl import ResourceType
from api.models.acl import Resource
from api.lib.perm.acl.cache import UserCache
from api.lib.perm.acl.permission import PermissionCRUD
from api.lib.perm.acl.resource import ResourceCRUD
from api.lib.perm.acl.role import RoleCRUD
from api.models.acl import Resource
from api.models.acl import ResourceGroup
from api.models.acl import ResourceType
from api.models.acl import Role
CMDB_RESOURCE_TYPES = CmdbResourceType.all()
class ACLManager(object):
def __init__(self):
self.user_info = session["acl"] if "acl" in session else {}
self.app_id = AppCache.get('cmdb')
if not self.app_id:
raise Exception("cmdb not in acl apps")
self.app_id = self.app_id.id
def add_resource(self, name, resource_type_name=None):
def _get_resource(self, name, resource_type_name):
resource_type = ResourceType.get_by(name=resource_type_name, first=True, to_dict=False)
if resource_type:
return abort(400, "ResourceType <{0}> cannot be found".format(resource_type_name))
resource_type or abort(404, "ResourceType <{0}> cannot be found".format(resource_type_name))
ResourceCRUD.add(name, resource_type.id, self.app_id)
def grant_resource_to_role(self, name, role, resource_type_name=None):
resource_type = ResourceType.get_by(name=resource_type_name, first=True, to_dict=False)
if resource_type:
return abort(400, "ResourceType <{0}> cannot be found".format(resource_type_name))
def del_resource(self, name, resource_type_name=None):
resource_type = ResourceType.get_by(name=resource_type_name, first=True, to_dict=False)
if resource_type:
return abort(400, "ResourceType <{0}> cannot be found".format(resource_type_name))
resource = Resource.get_by(resource_type_id=resource_type.id,
return Resource.get_by(resource_type_id=resource_type.id,
app_id=self.app_id,
name=name,
first=True,
to_dict=False)
def _get_resource_group(self, name):
return ResourceGroup.get_by(
app_id=self.app_id,
name=name,
first=True,
to_dict=False
)
def _get_role(self, name):
user = UserCache.get(name)
if user:
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)
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 or abort(404, "ResourceType <{0}> cannot be found".format(resource_type_name))
ResourceCRUD.add(name, resource_type.id, self.app_id)
def grant_resource_to_role(self, name, role, resource_type_name=None, permissions=None):
resource = self._get_resource(name, resource_type_name)
role = self._get_role(role)
if resource:
PermissionCRUD.grant(role.id, permissions, resource_id=resource.id)
else:
group = self._get_resource_group(name)
if group:
PermissionCRUD.grant(role.id, permissions, group_id=group.id)
def del_resource(self, name, resource_type_name=None):
resource = self._get_resource(name, resource_type_name)
if resource:
ResourceCRUD.delete(resource.id)
def get_resources(self, resource_type_name=None):
if "acl" not in session:
abort(405)
return []
def has_permission(self, resource_name, resource_type, perm):
if "acl" not in session:
abort(405)
return True
role = self._get_role(g.user.username)
role or abort(404, "Role <{0}> is not found".format(g.user.username))
return RoleCRUD.has_permission(role.id, resource_name, resource_type, self.app_id, perm)
def validate_permission(resources, resource_type, perm):
@ -70,24 +99,6 @@ def validate_permission(resources, resource_type, perm):
return abort(403, "has no permission")
def can_access_resources(resource_type):
def decorator_can_access_resources(func):
@functools.wraps(func)
def wrapper_can_access_resources(*args, **kwargs):
if current_app.config.get("USE_ACL"):
res = ACLManager().get_resources(resource_type)
result = {i.get("name"): i.get("permissions") for i in res}
if hasattr(g, "resources"):
g.resources.update({resource_type: result})
else:
g.resources = {resource_type: result}
return func(*args, **kwargs)
return wrapper_can_access_resources
return decorator_can_access_resources
def has_perm(resources, resource_type, perm):
def decorator_has_perm(func):
@functools.wraps(func)
@ -96,6 +107,9 @@ def has_perm(resources, resource_type, perm):
return
if current_app.config.get("USE_ACL"):
if is_app_admin():
return func(*args, **kwargs)
validate_permission(resources, resource_type, perm)
return func(*args, **kwargs)
@ -105,6 +119,13 @@ def has_perm(resources, resource_type, perm):
return decorator_has_perm
def is_app_admin():
if RoleEnum.CONFIG in session.get("acl", {}).get("parentRoles", []):
return True
return False
def has_perm_from_args(arg_name, resource_type, perm, callback=None):
def decorator_has_perm(func):
@functools.wraps(func)
@ -116,6 +137,9 @@ def has_perm_from_args(arg_name, resource_type, perm, callback=None):
resource = callback(resource)
if current_app.config.get("USE_ACL") and resource:
if is_app_admin():
return func(*args, **kwargs)
validate_permission(resource, resource_type, perm)
return func(*args, **kwargs)

View File

@ -1,4 +1,5 @@
# -*- coding:utf-8 -*-
from api.lib.cmdb.const import CMDB_QUEUE
ACL_QUEUE = "acl_async"
ACL_QUEUE = CMDB_QUEUE

View File

@ -3,7 +3,9 @@
from api.lib.perm.acl.cache import PermissionCache
from api.lib.perm.acl.cache import RoleCache
from api.lib.perm.acl.const import ACL_QUEUE
from api.models.acl import RolePermission
from api.tasks.acl import role_rebuild
class PermissionCRUD(object):
@ -29,6 +31,8 @@ class PermissionCRUD(object):
existed = RolePermission.get_by(rid=rid, perm_id=perm.id, group_id=group_id, resource_id=resource_id)
existed or RolePermission.create(rid=rid, perm_id=perm.id, group_id=group_id, resource_id=resource_id)
role_rebuild.apply_async(args=(rid,), queue=ACL_QUEUE)
@staticmethod
def revoke(rid, perms, resource_id=None, group_id=None):
for perm in perms:
@ -40,3 +44,5 @@ class PermissionCRUD(object):
first=True,
to_dict=False)
existed and existed.soft_delete()
role_rebuild.apply_async(args=(rid,), queue=ACL_QUEUE)

View File

@ -4,11 +4,14 @@
from flask import abort
from api.extensions import db
from api.lib.perm.acl.const import ACL_QUEUE
from api.models.acl import Permission
from api.models.acl import Resource
from api.models.acl import ResourceGroup
from api.models.acl import ResourceGroupItems
from api.models.acl import ResourceType
from api.models.acl import RolePermission
from api.tasks.acl import role_rebuild
class ResourceTypeCRUD(object):
@ -134,6 +137,10 @@ class ResourceGroupCRUD(object):
for item in items:
item.soft_delete()
for i in RolePermission.get_by(group_id=rg_id, to_dict=False):
i.soft_delete()
role_rebuild.apply_async(args=(i.rid,), queue=ACL_QUEUE)
class ResourceCRUD(object):
@staticmethod
@ -173,3 +180,7 @@ class ResourceCRUD(object):
resource = Resource.get_by_id(_id) or abort(404, "Resource <{0}> is not found".format(_id))
resource.soft_delete()
for i in RolePermission.get_by(resource_id=_id, to_dict=False):
i.soft_delete()
role_rebuild.apply_async(args=(i.rid,), queue=ACL_QUEUE)

View File

@ -10,6 +10,7 @@ from api.lib.perm.acl.cache import RoleRelationCache
from api.lib.perm.acl.const import ACL_QUEUE
from api.models.acl import Resource
from api.models.acl import ResourceGroupItems
from api.models.acl import ResourceType
from api.models.acl import Role
from api.models.acl import RolePermission
from api.models.acl import RoleRelation
@ -44,7 +45,7 @@ class RoleRelationCRUD(object):
@staticmethod
def get_child_ids(rid):
res = RoleRelation.get_by(child_id=rid, to_dict=False)
res = RoleRelation.get_by(parent_id=rid, to_dict=False)
return [i.parent_id for i in res]
@ -82,27 +83,37 @@ class RoleRelationCRUD(object):
return RoleRelation.create(parent_id=parent_id, child_id=child_id)
@staticmethod
def delete(_id):
@classmethod
def delete(cls, _id):
existed = RoleRelation.get_by_id(_id) or abort(400, "RoleRelation <{0}> does not exist".format(_id))
child_ids = cls.recursive_child_ids(existed.child_id)
for child_id in child_ids:
role_rebuild.apply_async(args=(child_id,), queue=ACL_QUEUE)
existed.soft_delete()
@staticmethod
def delete2(parent_id, child_id):
@classmethod
def delete2(cls, parent_id, child_id):
existed = RoleRelation.get_by(parent_id=parent_id, child_id=child_id, first=True, to_dict=False)
existed or abort(400, "RoleRelation < {0} -> {1} > does not exist".format(parent_id, child_id))
child_ids = cls.recursive_child_ids(existed.child_id)
for child_id in child_ids:
role_rebuild.apply_async(args=(child_id,), queue=ACL_QUEUE)
existed.soft_delete()
class RoleCRUD(object):
@staticmethod
def search(q, app_id, page=1, page_size=None, user_role=False):
query = db.session.query(Role).filter(Role.deleted.is_(False)).filter(Role.app_id == app_id)
def search(q, app_id, page=1, page_size=None, user_role=True):
query = db.session.query(Role).filter(Role.deleted.is_(False))
query = query.filter(Role.app_id == app_id).filter(Role.uid.is_(None))
if not user_role:
query = query.filter(Role.uid.is_(None))
if user_role:
query1 = db.session.query(Role).filter(Role.deleted.is_(False)).filter(Role.uid.isnot(None))
query = query.union(query1)
if q:
query = query.filter(Role.name.ilike('%{0}%'.format(q)))
@ -134,9 +145,6 @@ class RoleCRUD(object):
def delete_role(cls, rid):
role = Role.get_by_id(rid) or abort(404, "Role <{0}> does not exist".format(rid))
parent_ids = RoleRelationCRUD.get_parent_ids(rid)
child_ids = RoleRelationCRUD.get_child_ids(rid)
for i in RoleRelation.get_by(parent_id=rid, to_dict=False):
i.soft_delete()
for i in RoleRelation.get_by(child_id=rid, to_dict=False):
@ -145,7 +153,7 @@ class RoleCRUD(object):
for i in RolePermission.get_by(rid=rid, to_dict=False):
i.soft_delete()
role_rebuild.apply_async(args=(parent_ids + child_ids,), queue=ACL_QUEUE)
role_rebuild.apply_async(args=(list(RoleRelationCRUD.recursive_child_ids(rid)), ), queue=ACL_QUEUE)
RoleCache.clean(rid)
RoleRelationCache.clean(rid)
@ -166,20 +174,21 @@ class RoleCRUD(object):
@staticmethod
def get_group_ids(resource_id):
return [i.group_id for i in ResourceGroupItems.get_by(resource_id, to_dict=False)]
return [i.group_id for i in ResourceGroupItems.get_by(resource_id=resource_id, to_dict=False)]
@classmethod
def has_permission(cls, rid, resource_name, perm):
resource = Resource.get_by(name=resource_name, first=True, to_dict=False)
def has_permission(cls, rid, resource_name, resource_type, app_id, perm):
resource_type = ResourceType.get_by(app_id=app_id, name=resource_type, first=True, to_dict=False)
resource_type or abort(404, "ResourceType <{0}> is not found".format(resource_type))
type_id = resource_type.id
resource = Resource.get_by(name=resource_name, resource_type_id=type_id, first=True, to_dict=False)
resource = resource or abort(403, "Resource <{0}> is not in ACL".format(resource_name))
parent_ids = RoleRelationCRUD.recursive_parent_ids(rid)
group_ids = cls.get_group_ids(resource.id)
for parent_id in parent_ids:
id2perms = RoleRelationCache.get_resources(parent_id)
perms = id2perms['id2perms'].get(resource.id, [])
if perms and {perm}.issubset(set(perms)):
return True

View File

@ -136,9 +136,6 @@ class RoleRelation(Model):
parent_id = db.Column(db.Integer, db.ForeignKey('acl_roles.id'))
child_id = db.Column(db.Integer, db.ForeignKey('acl_roles.id'))
__table_args__ = (
db.UniqueConstraint("parent_id", "child_id", name="role_relation_unique"),)
class ResourceType(Model):
__tablename__ = "acl_resource_types"
@ -156,8 +153,6 @@ class ResourceGroup(Model):
app_id = db.Column(db.Integer, db.ForeignKey('acl_apps.id'))
__table_args__ = (db.UniqueConstraint("name", "resource_type_id", "app_id", name="resource_group_app_unique"),)
class Resource(Model):
__tablename__ = "acl_resources"
@ -167,8 +162,6 @@ class Resource(Model):
app_id = db.Column(db.Integer, db.ForeignKey("acl_apps.id"))
__table_args__ = (db.UniqueConstraint("name", "resource_type_id", "app_id", name="resource_name_app_unique"),)
class ResourceGroupItems(Model):
__tablename__ = "acl_resource_group_items"
@ -185,8 +178,6 @@ class Permission(Model):
app_id = db.Column(db.Integer, db.ForeignKey("acl_apps.id"))
__table_args__ = (db.UniqueConstraint("name", "resource_type_id", "app_id", name="perm_name_app_unique"),)
class RolePermission(Model):
__tablename__ = "acl_role_permissions"

View File

@ -79,3 +79,6 @@ USE_ACL = False
# # elastic search
ES_HOST = '127.0.0.1'
USE_ES = False
BOOL_TRUE = ['true', 'TRUE', 'True', True, '1', 1, "Yes", "YES", "yes", 'Y', 'y']

View File

@ -13,4 +13,4 @@ def role_rebuild(rids):
for rid in rids:
RoleRelationCache.rebuild(rid)
current_app.logger.info("%d rebuild.........." % rids)
current_app.logger.info("Role {0} rebuild..........".format(rids))

View File

@ -50,8 +50,8 @@ def ci_relation_cache(parent_id, child_id):
children = json.loads(children) if children is not None else {}
cr = CIRelation.get_by(first_ci_id=parent_id, second_ci_id=child_id, first=True, to_dict=False)
if child_id not in children:
children[child_id] = cr.second_ci.type_id
if str(child_id) not in children:
children[str(child_id)] = cr.second_ci.type_id
rd.create_or_update({parent_id: json.dumps(children)}, REDIS_PREFIX_CI_RELATION)
@ -63,8 +63,8 @@ def ci_relation_delete(parent_id, child_id):
children = rd.get([parent_id], REDIS_PREFIX_CI_RELATION)[0]
children = json.loads(children) if children is not None else {}
if child_id in children:
children.pop(child_id)
if str(child_id) in children:
children.pop(str(child_id))
rd.create_or_update({parent_id: json.dumps(children)}, REDIS_PREFIX_CI_RELATION)

View File

@ -6,12 +6,15 @@ import jwt
from flask import abort
from flask import current_app
from flask import request
from flask import session
from flask_login import login_user, logout_user
from api.lib.decorator import args_required
from api.lib.perm.auth import auth_abandoned
from api.models.acl import User
from api.models.acl import User, Role
from api.resource import APIView
from api.lib.perm.acl.role import RoleRelationCRUD
from api.lib.perm.acl.cache import RoleCache
class LoginView(APIView):
@ -37,6 +40,18 @@ class LoginView(APIView):
'exp': datetime.datetime.now() + datetime.timedelta(minutes=24 * 60 * 7)},
current_app.config['SECRET_KEY'])
role = Role.get_by(uid=user.uid, first=True, to_dict=False)
if role:
parent_ids = RoleRelationCRUD.recursive_parent_ids(role.id)
parent_roles = [RoleCache.get(i).name for i in parent_ids]
else:
parent_roles = []
session["acl"] = dict(uid=user.uid,
avatar=user.avatar,
userName=user.username,
nickName=user.nickname,
parentRoles=parent_roles)
return self.jsonify(token=token.decode())

View File

@ -1,5 +1,6 @@
# -*- coding:utf-8 -*-
from flask import current_app
from flask import request
from api.lib.decorator import args_required
@ -21,7 +22,8 @@ class RoleView(APIView):
page_size = get_page_size(request.values.get("page_size"))
q = request.values.get('q')
app_id = request.values.get('app_id')
user_role = request.values.get('user_role', False)
user_role = request.values.get('user_role', True)
user_role = True if user_role in current_app.config.get("BOOL_TRUE") else False
numfound, roles = RoleCRUD.search(q, app_id, page, page_size, user_role)

View File

@ -17,9 +17,9 @@ class GetUserInfoView(APIView):
url_prefix = "/users/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
name = session.get("CAS_USERNAME") or current_user.nickname
role = dict(permissions=session.get("acl", {}).get("parentRoles", []))
avatar = current_user.avatar
return self.jsonify(result=dict(name=name,
role=role,
avatar=avatar))

View File

@ -10,7 +10,7 @@ from flask import request
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 ResourceType, PermEnum
from api.lib.cmdb.const import ResourceTypeEnum, PermEnum
from api.lib.cmdb.const import RetKey
from api.lib.cmdb.search import SearchError
from api.lib.cmdb.search.ci.db.search import Search as SearchFromDB
@ -73,7 +73,7 @@ class CIView(APIView):
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)
@has_perm_from_args("ci_type", ResourceTypeEnum.CI, PermEnum.ADD)
def post(self):
ci_type = request.values.get("ci_type")
_no_attribute_policy = request.values.get("_no_attribute_policy", ExistPolicy.IGNORE)
@ -87,7 +87,7 @@ class CIView(APIView):
_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)
@has_perm_from_args("ci_id", ResourceTypeEnum.CI, PermEnum.UPDATE, CIManager.get_type_name)
def put(self, ci_id=None):
args = request.values
ci_type = args.get("ci_type")
@ -104,7 +104,7 @@ class CIView(APIView):
**ci_dict)
return self.jsonify(ci_id=ci_id)
@has_perm_from_args("ci_id", ResourceType.CI, PermEnum.DELETE, CIManager.get_type_name)
@has_perm_from_args("ci_id", ResourceTypeEnum.CI, PermEnum.DELETE, CIManager.get_type_name)
def delete(self, ci_id):
manager = CIManager()
manager.delete(ci_id)
@ -163,7 +163,7 @@ class CISearchView(APIView):
class CIUnique(APIView):
url_prefix = "/ci/<int:ci_id>/unique"
@has_perm_from_args("ci_id", ResourceType.CI, PermEnum.UPDATE, CIManager.get_type_name)
@has_perm_from_args("ci_id", ResourceTypeEnum.CI, PermEnum.UPDATE, CIManager.get_type_name)
def put(self, ci_id):
params = request.values
unique_name = params.keys()[0]

View File

@ -7,6 +7,7 @@ from flask import abort
from flask import current_app
from flask import request
from api.lib.cmdb.cache import RelationTypeCache
from api.lib.cmdb.ci import CIRelationManager
from api.lib.cmdb.search import SearchError
from api.lib.cmdb.search.ci_relation.search import Search
@ -83,11 +84,15 @@ class GetSecondCIsView(APIView):
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")
relation_type = request.values.get("relation_type")
try:
relation_type_id = RelationTypeCache.get(relation_type).id if relation_type else None
except AttributeError:
return abort(400, "invalid relation type <{0}>".format(relation_type))
manager = CIRelationManager()
numfound, total, second_cis = manager.get_second_cis(
first_ci_id, page=page, per_page=count, relation_type=relation_type)
first_ci_id, page=page, per_page=count, relation_type_id=relation_type_id)
return self.jsonify(numfound=numfound,
total=total,

View File

@ -4,7 +4,7 @@
from flask import request
from api.lib.cmdb.ci_type import CITypeManager
from api.lib.cmdb.const import ResourceType, PermEnum, RoleEnum
from api.lib.cmdb.const import ResourceTypeEnum, PermEnum, RoleEnum
from api.lib.cmdb.preference import PreferenceManager
from api.lib.decorator import args_required
from api.lib.perm.acl.acl import has_perm_from_args
@ -31,7 +31,7 @@ class PreferenceShowAttributesView(APIView):
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)
@has_perm_from_args("id_or_name", ResourceTypeEnum.CI, PermEnum.READ, CITypeManager.get_name_by_id)
@args_required("attr")
def post(self, id_or_name):
id_or_name = int(id_or_name)
@ -42,7 +42,7 @@ class PreferenceShowAttributesView(APIView):
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)
@has_perm_from_args("id_or_name", ResourceTypeEnum.CI, PermEnum.READ, CITypeManager.get_name_by_id)
def put(self, id_or_name):
return self.post(id_or_name)
@ -53,7 +53,7 @@ class PreferenceTreeApiView(APIView):
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)
@has_perm_from_args("type_id", ResourceTypeEnum.CI, PermEnum.READ, CITypeManager.get_name_by_id)
@args_required("type_id")
@args_required("levels")
def post(self):
@ -85,9 +85,11 @@ class PreferenceRelationApiView(APIView):
return self.jsonify(views=views, id2type=id2type, name2id=name2id)
@role_required(RoleEnum.CONFIG)
def put(self):
return self.post()
@role_required(RoleEnum.CONFIG)
@args_required("name")
def delete(self):
name = request.values.get("name")