def __init__(self, user): super().__init__(None) self.permissions = Permissions(user) self.pset = self.permissions self.set_peeringdb_handlers() if self.is_generating_api_cache: self.drop_namespace_key = False
def get_permissions(self, obj): perms = Permissions(obj) rv = { ns: { "perms": perms.get(ns.format(org_id=obj.org.id), as_string=True), "label": label, } for ns, label in self.permission_namespaces } return rv
def authenticate(self, request): key = key_from_request(request) api_key = None key_models = [APIKey, OrganizationAPIKey, InternalAPIKey] for model in key_models: try: if key: # a matching key was found api_key = model.objects.get(key=key) request.api_key = api_key if model == APIKey: # personal api key if not api_key.managed: # unmanaged personal keys have their own set of permissions request.perms = Permissions(api_key) else: # managed personal keys inherit the users permissions request.perms = Permissions(api_key.user) return (api_key.user, None) if model == OrganizationAPIKey: # Organization API Key request.perms = Permissions(api_key) return (api_key, None) if model == InternalAPIKey: # Inernal API Key return (api_key, None) else: return None except model.DoesNotExist: pass if not api_key: raise exceptions.AuthenticationFailed("Invalid api key")
def get_permissions(self, obj): perms = Permissions(obj.user) rv = { ns: { "perms": perms.get(ns.format(org_id=obj.org.id), as_string=True), "label": label, } for ns, label in self.permission_namespaces } # for svc in self.context.get("services",[]): # rv[svc.slug] = perms.get([obj.org, svc], as_string=True) return rv
def test_permissions_init(self): """ test django.grainy.util.Permissions.__init__ """ user = self.users["user_a"] group = self.groups["group_a"] api_key = self.api_key self.assertEqual(Permissions(user).obj, user) self.assertEqual(Permissions(group).obj, group) self.assertEqual(Permissions(api_key).obj, api_key) with self.assertRaises(ValueError): Permissions(object())
class APIPermissionsApplicator(NamespaceKeyApplicator): @property def is_generating_api_cache(self): try: return getattr(settings, "GENERATING_API_CACHE", False) except IndexError: return False def __init__(self, user): super().__init__(None) self.permissions = Permissions(user) self.pset = self.permissions self.set_peeringdb_handlers() if self.is_generating_api_cache: self.drop_namespace_key = False def set_peeringdb_handlers(self): self.handler( "peeringdb.organization.*.network.*.poc_set.private", explicit=True ) self.handler("peeringdb.organization.*.network.*.poc_set.users", explicit=True) self.handler( "peeringdb.organization.*.internetexchange.*", fn=self.handle_ixlan ) def handle_ixlan(self, namespace, data): if "ixf_ixp_member_list_url" in data: visible = data["ixf_ixp_member_list_url_visible"].lower() _namespace = f"{namespace}.ixf_ixp_member_list_url.{visible}" perms = self.permissions.check(_namespace, 0x01, explicit=True) if not perms: del data["ixf_ixp_member_list_url"]
def test_permissions_get(self): """ test django.grainy.util.Permissions.get """ perms = Permissions(self.users["user_a"]) self.assertEqual(perms.get(ModelA), PERM_READ) self.assertEqual(perms.get(ModelA, as_string=True), "r") self.assertEqual(perms.get(ModelB), PERM_READ | PERM_UPDATE) self.assertEqual(perms.get(ModelB, as_string=True), "ru") self.assertEqual(perms.get("detail_manual", as_string=True), "c") self.assertEqual( perms.get("detail_manual.1", as_string=True, explicit=True), "crud") self.assertEqual( perms.get("detail_manual.2", as_string=True, explicit=True), "") self.assertEqual(perms.get("detail_manual.2", as_string=True), "c")
def init_permissions_helper(obj): """Initializes the Permission Util based on if the provided object is a UserAPIKey, OrgAPIKey, or a different object. """ if isinstance(obj, UserAPIKey): return return_user_api_key_perms(obj) if isinstance(obj, OrganizationAPIKey): return return_org_api_key_perms(obj) else: return Permissions(obj)
class Organization(serializers.ModelSerializer): ref_tag = "org" personal = serializers.SerializerMethodField() label = serializers.CharField(read_only=True) selected = serializers.SerializerMethodField() is_admin = serializers.SerializerMethodField() class Meta: model = models.Organization fields = ["id", "name", "label", "slug", "selected", "personal", "is_admin"] def get_personal(self, obj): if obj.user == self.context.get("user"): return True return False def get_selected(self, obj): selected_org = self.context.get("selected_org") return selected_org and selected_org.id == obj.id def get_is_admin(self, obj): user = self.context.get("user") if not hasattr(self, "_perms"): self._perms = Permissions(user) return self._perms.check(obj, "crud") def validate(self, data): user = self.context.get("user") if not user: raise serializers.ValidationError("No user context") form = forms.CreateOrganization(data) if not form.is_valid(): raise serializers.ValidationError(form.errors) return data def save(self): data = self.validated_data org = models.Organization.objects.create( name=data.get("name"), slug=data.get("slug") ) org.add_user(self.context.get("user"), "crud") return org
def return_org_api_key_perms(key): """ Load Permissions util with OrgAPIKey perms and then add in that organization's user group perms and general user group permissions """ permissions = Permissions(key) # #Add user group perms org_usergroup = key.org.usergroup permissions.pset.update( org_usergroup.grainy_permissions.permission_set().permissions, override=False) # # Add general user group perms general_usergroup = Group.objects.get(id=settings.USER_GROUP_ID) permissions.pset.update( general_usergroup.grainy_permissions.permission_set().permissions, override=False, ) return permissions
def return_user_api_key_perms(key): """ Initializes the Permissions Util with the permissions of the user linked to the User API key. If the UserAPIKey is marked readonly, it downgrades all permissions to readonly. """ user = key.user permissions = Permissions(user) if key.readonly is True: readonly_perms = { ns: grainy_constant.PERM_READ for ns in permissions.pset.namespaces } permissions.pset.update(readonly_perms) return permissions
def test_anonymous_permissions(self): user = AnonymousUser() perms = Permissions(user) self.assertTrue(perms.check("a.b.c", PERM_READ)) self.assertTrue(perms.check("a.b.c.d", PERM_UPDATE | PERM_READ)) self.assertFalse(perms.check("x.y.z", PERM_READ))
import grainy.const from django_grainy.util import Permissions user.grainy_permissions.add_permission_set({"a.b.c": "r"}) # we use the Permissions() wrapper as that allows # us to do repeated permission checks for a user or group # without having requery permissions for each check perms = Permissions(user) perms.check("a.b.c", grainy.const.PERM_READ) #True perms.check("a.b.c.d", grainy.const.PERM_READ) #True perms.check("a.b.c.d", grainy.const.PERM_READ | grainy.const.PERM_UPDATE) #False perms.check("z.y.x", grainy.const.PERM_READ) #False perms.check("a.b.c", "r") # True perms.check("a.b.c.d", "r") # True perms.check("a.b.c.d", "ru") # False perms.check("x.y.z", "r") # False # The `explicit` option allows us to require that excplicit # permissions need to exist for a check to succeed, meaning # having permissions to `a.b.c` will not grant permissions # to `a.b.c.d` if `explicit`=True perms.check("a.b.c.d", "r", explicit=True) # False
def __init__(self, handle): from django.contrib.auth import get_user_model from django_grainy.util import Permissions from rest_framework.test import APIClient from account.models import ManagedPermission, Organization ManagedPermission.objects.get_or_create( namespace="org.{org_id}", description="", group="aaactl", auto_grant_admins=15, auto_grant_users=1, ) ManagedPermission.objects.get_or_create( namespace="user.{org_id}", description="", group="aaactl", auto_grant_admins=15, auto_grant_users=1, ) ManagedPermission.objects.get_or_create( namespace="billing.{org_id}", description="", group="aaactl", auto_grant_admins=15, auto_grant_users=1, ) self.user = user = get_user_model().objects.create_user( username=f"user_{handle}", email=f"{handle}@localhost", password="******", ) self.api_key = user.key_set.first() personal_org = user.personal_org personal_org.name = f"PersonalOrg{handle}" personal_org.slug = f"personalorg{handle}" personal_org.save() self.org = org = Organization.objects.create(name=handle, slug=handle) org.add_user(user, perms="crud") self.other_org = Organization.objects.create(name=f"Other {handle}", slug=f"other-{handle}") self.user_unpermissioned = ( user_unpermissioned) = get_user_model().objects.create_user( username=f"user_{handle}_unperm", email=f"{handle}_unperm@localhost", password="******", ) org.add_user(user_unpermissioned, perms="r") self.api_client = APIClient() self.api_client.login(username=user.username, password="******") self.api_client_unperm = APIClient() self.api_client_unperm.login(username=user_unpermissioned.username, password="******") self.api_client_anon = APIClient() self.client = Client() self.client.login(username=user.username, password="******") self.client_anon = Client() self.perms = Permissions(user)
from django_grainy.util import Permissions # give user full permissions to model (any instance) user.grainy_permissions.add(TestModelA, "crud") # give user full permissions to a specific instance instance = TestModelA.objects.get(id=1) user.grainy_permissions.add(instance, "crud") # check user permission on model class perms = Permissions(user) perms.check(TestModelA, "r") # True # check user permission on instance perms.check(instance, "r") # True # check permissions to the name field perms.check((instance, "name"), "r") # return all instances of the model according to permissions instances = perms.instances(TestModelA, "r") # this could also take a queryset instances = perms.instances(TestModelA.objects.filter(id__gt=10), "r")
def test_permissions_instances(self): """ test util.Permissions.instances """ perms_a = Permissions(self.users["user_a"]) perms_b = Permissions(self.users["user_b"]) perms_admin = Permissions(self.users["user_admin_a"]) for i in range(1, 4): ModelA.objects.create(name=f"Test {i}") # user a should have read to all 3 instances of model a # through implicit permissions instances = perms_a.instances(ModelA, "r") self.assertEqual(len(instances), 3) # user as should have read to to 0 instances of model a # through explicit permissions instances = perms_a.instances(ModelA, "r", explicit=True) self.assertEqual(len(instances), 0) # add user a permission to first isntance of model a # and reload permissions util self.users["user_a"].grainy_permissions.add_permission( ModelA.objects.first(), "r") perms_a.load(refresh=True) # user a should now habe read to 1 instances of model a # through explicit permissions instances = perms_a.instances(ModelA, "r", explicit=True) self.assertEqual(len(instances), 1) # user b should not have any instances = perms_b.instances(ModelA, "r") self.assertEqual(len(instances), 0) # deny user a permissions to first instance of model a # and reload permissions util self.users["user_a"].grainy_permissions.add_permission( ModelA.objects.first(), 0) perms_a.load(refresh=True) # user a should now have read access to 2 instances of model a instances = perms_a.instances(ModelA, "r") self.assertEqual(len(instances), 2) # admin user should have read to all 3 instances of model a # through grant all instances = perms_admin.instances(ModelA, "r") self.assertEqual(len(instances), 3) # admin user should have read to 0 instances of model # when ignoring grant all instances = perms_admin.instances(ModelA, "r", ignore_grant_all=True) self.assertEqual(len(instances), 0)
def get_for_user(cls, user, perms="r"): return Permissions(user).instances(cls, perms, ignore_grant_all=True)
def test_permissions_check(self): """ test django.grainy.util.Permissions.check """ user = self.users["user_a"] perms = Permissions(user) self.assertTrue(perms.check(ModelA, PERM_READ)) self.assertFalse(perms.check(ModelA, PERM_UPDATE)) self.assertTrue(perms.check(ModelB, PERM_READ)) self.assertTrue(perms.check(ModelB, PERM_UPDATE)) self.assertTrue(perms.check(ModelA(), PERM_READ)) self.assertFalse(perms.check(ModelA(), PERM_UPDATE)) self.assertTrue(perms.check(ModelB(), PERM_READ)) self.assertTrue(perms.check(ModelB(), PERM_UPDATE)) self.assertTrue(perms.check("secret.group", PERM_READ)) self.assertFalse(perms.check("secret", PERM_READ)) perms = Permissions(self.users["user_b"]) self.assertTrue(perms.check("x.y.z", PERM_READ)) self.assertFalse(perms.check("x.y.z", PERM_UPDATE)) perms = Permissions(self.users["user_admin_a"]) self.assertTrue(perms.check("x.y.z", PERM_READ)) self.assertFalse(perms.check("x.y.z", PERM_READ, ignore_grant_all=True)) perms = Permissions(self.api_key) self.assertTrue(perms.check(ModelA, PERM_READ)) self.assertFalse(perms.check(ModelA, PERM_UPDATE)) self.assertTrue(perms.check(ModelB, PERM_READ)) self.assertTrue(perms.check(ModelB, PERM_UPDATE)) self.assertTrue(perms.check(ModelA(), PERM_READ)) self.assertFalse(perms.check(ModelA(), PERM_UPDATE)) self.assertTrue(perms.check(ModelB(), PERM_READ)) self.assertTrue(perms.check(ModelB(), PERM_UPDATE))
def get_is_admin(self, obj): user = self.context.get("user") if not hasattr(self, "_perms"): self._perms = Permissions(user) return self._perms.check(obj, "crud")
from django.db import modelsi from django_grainy.models import GrainyMixin, Permission, PermissionManager class APIKey(models.Model): key = models.CharField(max_length=255) class APIKeyPermission(Permission): # The `grainy_permissions` related name is important # so that we can pass instances of this model to # util.Permissions api_key = models.ForeignKey(APIKey, related_name="grainy_permissions", on_delete=models.CASCADE) # use the augmented object manager for permission handling objects = PermissionManager() from django_grainy.util import Permissions api_key = APIKey.objects.create(key="test") api_key.grainy_permissions.add_permission("a.b.c", "r") perms = Permissions(api_key) assert api_key.check("a.b.c", "r")
def process_view(self, request, view_func, view_args, view_kwargs): request.perms = Permissions(request.user) self.set_selected_org(request)