ACL: permission management [doing]

This commit is contained in:
pycook 2019-12-04 18:14:09 +08:00
parent e73810b456
commit 6973cc68ed
6 changed files with 68 additions and 44 deletions

View File

@ -3,52 +3,47 @@
import functools
import six
from flask import current_app, g, request
from flask import session, abort
from api.extensions import cache
def get_access_token():
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")
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.resource import ResourceCRUD
class ACLManager(object):
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.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):
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):
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):
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):
return dict()
resource = Resource.get_by(resource_type_id=resource_type.id,
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):
if "acl" not in session:
@ -87,7 +82,9 @@ def can_access_resources(resource_type):
else:
g.resources = {resource_type: result}
return func(*args, **kwargs)
return wrapper_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)
return func(*args, **kwargs)
return wrapper_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)
return func(*args, **kwargs)
return wrapper_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", []):
return abort(403, "Role {0} is required".format(role_name))
return func(*args, **kwargs)
return wrapper_role_required
return decorator_role_required

View File

@ -36,11 +36,11 @@ class ResourceTypeCRUD(object):
return [i.to_dict() for i in perms]
@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(
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)

View File

@ -23,8 +23,8 @@ class RoleRelationCRUD(object):
if uids is not None:
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))
rid2uid = {i.rid: i.uid for i in rids}
rids = [i.rid for i in rids]
rid2uid = {i.id: i.uid for i in rids}
rids = [i.id for i in rids]
else:
rids = [rids] if isinstance(rids, six.integer_types) else rids
@ -98,9 +98,12 @@ class RoleRelationCRUD(object):
class RoleCRUD(object):
@staticmethod
def search(q, app_id, page=1, page_size=None):
query = db.session.query(Role).filter(Role.deleted.is_(False)).filter(
Role.app_id == app_id).filter(Role.uid.is_(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(Role.app_id == app_id)
if not user_role:
query = query.filter(Role.uid.is_(None))
if 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)
@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))
return Role.create(name=name,

View File

@ -1,15 +1,17 @@
# -*- coding:utf-8 -*-
import uuid
import string
import random
import string
import uuid
from flask import abort
from flask import g
from api.extensions import db
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
@ -40,14 +42,28 @@ class UserCRUD(object):
kwargs['block'] = 0
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
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))
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)
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)
@classmethod

View File

@ -39,9 +39,10 @@ class ResourceTypeView(APIView):
def post(self):
name = request.values.get('name')
app_id = request.values.get('app_id')
description = request.values.get('description', '')
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())

View File

@ -21,8 +21,9 @@ 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)
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])