mirror of https://github.com/veops/cmdb.git
ACL: permission management [doing]
This commit is contained in:
parent
e73810b456
commit
6973cc68ed
|
@ -3,52 +3,47 @@
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from flask import current_app, g, request
|
from flask import current_app, g, request
|
||||||
from flask import session, abort
|
from flask import session, abort
|
||||||
|
|
||||||
from api.extensions import cache
|
from api.lib.perm.acl.cache import AppCache
|
||||||
|
from api.models.acl import ResourceType
|
||||||
|
from api.models.acl import Resource
|
||||||
def get_access_token():
|
from api.lib.perm.acl.resource import ResourceCRUD
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
class AccessTokenCache(object):
|
|
||||||
@classmethod
|
|
||||||
def get(cls):
|
|
||||||
if cache.get("AccessToken") is not None:
|
|
||||||
return cache.get("AccessToken")
|
|
||||||
|
|
||||||
res = get_access_token() or ""
|
|
||||||
|
|
||||||
cache.set("AccessToken", res, timeout=60 * 60)
|
|
||||||
return res
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def clean(cls):
|
|
||||||
cache.clear("AccessToken")
|
|
||||||
|
|
||||||
|
|
||||||
class ACLManager(object):
|
class ACLManager(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.access_token = AccessTokenCache.get()
|
|
||||||
self.acl_session = dict(uid=session.get("uid"),
|
|
||||||
token=self.access_token)
|
|
||||||
|
|
||||||
self.user_info = session["acl"] if "acl" in session else {}
|
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 add_resource(self, name, resource_type_name=None):
|
||||||
pass
|
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))
|
||||||
|
|
||||||
|
ResourceCRUD.add(name, resource_type.id, self.app_id)
|
||||||
|
|
||||||
def grant_resource_to_role(self, name, role, resource_type_name=None):
|
def grant_resource_to_role(self, name, role, resource_type_name=None):
|
||||||
pass
|
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):
|
def del_resource(self, name, resource_type_name=None):
|
||||||
pass
|
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 get_user_info(self, username):
|
resource = Resource.get_by(resource_type_id=resource_type.id,
|
||||||
return dict()
|
app_id=self.app_id,
|
||||||
|
name=name,
|
||||||
|
first=True,
|
||||||
|
to_dict=False)
|
||||||
|
if resource:
|
||||||
|
ResourceCRUD.delete(resource.id)
|
||||||
|
|
||||||
def get_resources(self, resource_type_name=None):
|
def get_resources(self, resource_type_name=None):
|
||||||
if "acl" not in session:
|
if "acl" not in session:
|
||||||
|
@ -87,7 +82,9 @@ def can_access_resources(resource_type):
|
||||||
else:
|
else:
|
||||||
g.resources = {resource_type: result}
|
g.resources = {resource_type: result}
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
return wrapper_can_access_resources
|
return wrapper_can_access_resources
|
||||||
|
|
||||||
return decorator_can_access_resources
|
return decorator_can_access_resources
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,7 +99,9 @@ def has_perm(resources, resource_type, perm):
|
||||||
validate_permission(resources, resource_type, perm)
|
validate_permission(resources, resource_type, perm)
|
||||||
|
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
return wrapper_has_perm
|
return wrapper_has_perm
|
||||||
|
|
||||||
return decorator_has_perm
|
return decorator_has_perm
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,7 +119,9 @@ def has_perm_from_args(arg_name, resource_type, perm, callback=None):
|
||||||
validate_permission(resource, resource_type, perm)
|
validate_permission(resource, resource_type, perm)
|
||||||
|
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
return wrapper_has_perm
|
return wrapper_has_perm
|
||||||
|
|
||||||
return decorator_has_perm
|
return decorator_has_perm
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,5 +136,7 @@ def role_required(role_name):
|
||||||
if role_name not in session.get("acl", {}).get("parentRoles", []):
|
if role_name not in session.get("acl", {}).get("parentRoles", []):
|
||||||
return abort(403, "Role {0} is required".format(role_name))
|
return abort(403, "Role {0} is required".format(role_name))
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
return wrapper_role_required
|
return wrapper_role_required
|
||||||
|
|
||||||
return decorator_role_required
|
return decorator_role_required
|
||||||
|
|
|
@ -36,11 +36,11 @@ class ResourceTypeCRUD(object):
|
||||||
return [i.to_dict() for i in perms]
|
return [i.to_dict() for i in perms]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add(cls, app_id, name, perms):
|
def add(cls, app_id, name, description, perms):
|
||||||
ResourceType.get_by(name=name, app_id=app_id) and abort(
|
ResourceType.get_by(name=name, app_id=app_id) and abort(
|
||||||
400, "ResourceType <{0}> is already existed".format(name))
|
400, "ResourceType <{0}> is already existed".format(name))
|
||||||
|
|
||||||
rt = ResourceType.create(name=name, app_id=app_id)
|
rt = ResourceType.create(name=name, description=description, app_id=app_id)
|
||||||
|
|
||||||
cls.update_perms(rt.id, perms, app_id)
|
cls.update_perms(rt.id, perms, app_id)
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ class RoleRelationCRUD(object):
|
||||||
if uids is not None:
|
if uids is not None:
|
||||||
uids = [uids] if isinstance(uids, six.integer_types) else uids
|
uids = [uids] if isinstance(uids, six.integer_types) else uids
|
||||||
rids = db.session.query(Role).filter(Role.deleted.is_(False)).filter(Role.uid.in_(uids))
|
rids = db.session.query(Role).filter(Role.deleted.is_(False)).filter(Role.uid.in_(uids))
|
||||||
rid2uid = {i.rid: i.uid for i in rids}
|
rid2uid = {i.id: i.uid for i in rids}
|
||||||
rids = [i.rid for i in rids]
|
rids = [i.id for i in rids]
|
||||||
else:
|
else:
|
||||||
rids = [rids] if isinstance(rids, six.integer_types) else rids
|
rids = [rids] if isinstance(rids, six.integer_types) else rids
|
||||||
|
|
||||||
|
@ -98,9 +98,12 @@ class RoleRelationCRUD(object):
|
||||||
|
|
||||||
class RoleCRUD(object):
|
class RoleCRUD(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def search(q, app_id, page=1, page_size=None):
|
def search(q, app_id, page=1, page_size=None, user_role=False):
|
||||||
query = db.session.query(Role).filter(Role.deleted.is_(False)).filter(
|
query = db.session.query(Role).filter(Role.deleted.is_(False)).filter(Role.app_id == app_id)
|
||||||
Role.app_id == app_id).filter(Role.uid.is_(None))
|
|
||||||
|
if not user_role:
|
||||||
|
query = query.filter(Role.uid.is_(None))
|
||||||
|
|
||||||
if q:
|
if q:
|
||||||
query = query.filter(Role.name.ilike('%{0}%'.format(q)))
|
query = query.filter(Role.name.ilike('%{0}%'.format(q)))
|
||||||
|
|
||||||
|
@ -109,7 +112,7 @@ class RoleCRUD(object):
|
||||||
return numfound, query.offset((page - 1) * page_size).limit(page_size)
|
return numfound, query.offset((page - 1) * page_size).limit(page_size)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_role(name, app_id, is_app_admin=False, uid=None):
|
def add_role(name, app_id=None, is_app_admin=False, uid=None):
|
||||||
Role.get_by(name=name, app_id=app_id) and abort(400, "Role <{0}> is already existed".format(name))
|
Role.get_by(name=name, app_id=app_id) and abort(400, "Role <{0}> is already existed".format(name))
|
||||||
|
|
||||||
return Role.create(name=name,
|
return Role.create(name=name,
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
import uuid
|
|
||||||
import string
|
|
||||||
import random
|
import random
|
||||||
|
import string
|
||||||
|
import uuid
|
||||||
|
|
||||||
from flask import abort
|
from flask import abort
|
||||||
from flask import g
|
from flask import g
|
||||||
|
|
||||||
from api.extensions import db
|
from api.extensions import db
|
||||||
from api.lib.perm.acl.cache import UserCache
|
from api.lib.perm.acl.cache import UserCache
|
||||||
|
from api.lib.perm.acl.role import RoleCRUD
|
||||||
|
from api.models.acl import Role
|
||||||
from api.models.acl import User
|
from api.models.acl import User
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,14 +42,28 @@ 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()
|
||||||
|
|
||||||
return User.create(**kwargs)
|
user = User.create(**kwargs)
|
||||||
|
|
||||||
|
RoleCRUD.add_role(user.username, uid=user.uid)
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update(uid, **kwargs):
|
def update(uid, **kwargs):
|
||||||
user = User.get_by(uid=uid, to_dict=False, first=True) or abort(404, "User <{0}> does not exist".format(uid))
|
user = User.get_by(uid=uid, to_dict=False, first=True) or abort(404, "User <{0}> does not exist".format(uid))
|
||||||
|
|
||||||
|
if kwargs.get("username"):
|
||||||
|
other = User.get_by(username=kwargs['username'], first=True, to_dict=False)
|
||||||
|
if other is not None and other.uid != user.uid:
|
||||||
|
return abort(400, "User <{0}> cannot be duplicated".format(kwargs['username']))
|
||||||
|
|
||||||
UserCache.clean(user)
|
UserCache.clean(user)
|
||||||
|
|
||||||
|
if kwargs.get("username") and kwargs['username'] != user.username:
|
||||||
|
role = Role.get_by(name=user.username, first=True, to_dict=False)
|
||||||
|
if role is not None:
|
||||||
|
RoleCRUD.update_role(role.id, **dict(name=kwargs['name']))
|
||||||
|
|
||||||
return user.update(**kwargs)
|
return user.update(**kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -39,9 +39,10 @@ class ResourceTypeView(APIView):
|
||||||
def post(self):
|
def post(self):
|
||||||
name = request.values.get('name')
|
name = request.values.get('name')
|
||||||
app_id = request.values.get('app_id')
|
app_id = request.values.get('app_id')
|
||||||
|
description = request.values.get('description', '')
|
||||||
perms = request.values.get('perms')
|
perms = request.values.get('perms')
|
||||||
|
|
||||||
rt = ResourceTypeCRUD.add(app_id, name, perms)
|
rt = ResourceTypeCRUD.add(app_id, name, description, perms)
|
||||||
|
|
||||||
return self.jsonify(rt.to_dict())
|
return self.jsonify(rt.to_dict())
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,9 @@ class RoleView(APIView):
|
||||||
page_size = get_page_size(request.values.get("page_size"))
|
page_size = get_page_size(request.values.get("page_size"))
|
||||||
q = request.values.get('q')
|
q = request.values.get('q')
|
||||||
app_id = request.values.get('app_id')
|
app_id = request.values.get('app_id')
|
||||||
|
user_role = request.values.get('user_role', False)
|
||||||
|
|
||||||
numfound, roles = RoleCRUD.search(q, app_id, page, page_size)
|
numfound, roles = RoleCRUD.search(q, app_id, page, page_size, user_role)
|
||||||
|
|
||||||
id2parents = RoleRelationCRUD.get_parents([i.id for i in roles])
|
id2parents = RoleRelationCRUD.get_parents([i.id for i in roles])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue