-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #27 from jaredlewis/develop
Updates to registration logic, ability to add custom PermSet
- Loading branch information
Showing
12 changed files
with
635 additions
and
347 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
from django.contrib.contenttypes.models import ContentType | ||
from django.db import models | ||
from manager_utils import sync | ||
|
||
|
||
class PermSetManager(models.Manager): | ||
def sync_perm_sets(self, perm_sets): | ||
""" | ||
Syncs all private perm sets the provided dictionary of perm sets to PermSet models. | ||
""" | ||
from restraint.models import PermSet | ||
sync( | ||
queryset=self.get_queryset().filter( | ||
is_private=True | ||
), | ||
model_objs=[ | ||
PermSet( | ||
name=name, | ||
display_name=config.get('display_name', ''), | ||
is_private=True | ||
) | ||
for name, config in perm_sets.items() | ||
], | ||
unique_fields=[ | ||
'name' | ||
], | ||
update_fields=[ | ||
'display_name' | ||
] | ||
) | ||
|
||
|
||
class PermManager(models.Manager): | ||
def sync_perms(self, perms): | ||
""" | ||
Syncs the perms to Perm models. | ||
""" | ||
from restraint.models import Perm | ||
return sync( | ||
queryset=self.get_queryset(), | ||
model_objs=[ | ||
Perm( | ||
name=name, | ||
display_name=config.get('display_name', '') | ||
) | ||
for name, config in perms.items() | ||
], | ||
unique_fields=[ | ||
'name' | ||
], | ||
update_fields=[ | ||
'display_name' | ||
], | ||
return_upserts_distinct=True | ||
) | ||
|
||
|
||
class PermLevelManager(models.Manager): | ||
def sync_perm_levels(self, perms): | ||
""" | ||
Given a dictionary of perms that map to perm levels, sync the perm levels | ||
to PermLevel objects in the database. | ||
""" | ||
from restraint.models import Perm, PermLevel | ||
perm_objs = { | ||
p.name: p | ||
for p in Perm.objects.all() | ||
} | ||
perm_levels = [] | ||
for perm, perm_config in perms.items(): | ||
assert(perm_config['levels']) | ||
for level, level_config in perm_config['levels'].items(): | ||
perm_levels.append(PermLevel( | ||
perm=perm_objs[perm], | ||
name=level, | ||
display_name=level_config.get('display_name', '') | ||
)) | ||
sync( | ||
queryset=self.get_queryset(), | ||
model_objs=perm_levels, | ||
unique_fields=[ | ||
'name', | ||
'perm' | ||
], | ||
update_fields=[ | ||
'display_name' | ||
] | ||
) | ||
|
||
|
||
class PermAccessManager(models.Manager): | ||
def set_default(self, permission_set_name, permission_name, levels=None): | ||
""" | ||
Sets default levels for a permission for a permission set | ||
:param permission_set_name: The name of the permission set | ||
:param permission_name: The name of the permission | ||
:param levels: A list of levels | ||
""" | ||
from restraint.models import PermSet, PermAccess, PermLevel | ||
permission_access = PermAccess.objects.get_or_create( | ||
perm_set=PermSet.objects.get(name=permission_set_name) | ||
)[0] | ||
if levels: | ||
permission_levels = PermLevel.objects.filter( | ||
perm__name=permission_name, | ||
name__in=levels | ||
) | ||
permission_access.perm_levels.set(permission_levels) | ||
else: | ||
permission_access.perm_levels.clear() | ||
|
||
def update_perm_set_access(self, config, new_perms=None, flush_previous_config=False): | ||
""" | ||
Update the access for private perm sets with a config. The user can optionally flush | ||
the previous config and set it to the new one. | ||
""" | ||
|
||
# Do model imports to avoid circular | ||
from restraint.models import PermSet, PermAccess, PermLevel | ||
|
||
# Ensure that new perms is not none | ||
if new_perms is None: # pragma: no cover | ||
new_perms = [] | ||
|
||
# Loop over each private permission set | ||
for perm_set in PermSet.objects.filter(is_private=True): | ||
perm_access, created = PermAccess.objects.get_or_create(perm_set=perm_set) | ||
perm_access_levels = [] | ||
for perm, perm_levels in config.get(perm_set.name, {}).items(): | ||
# If we are not flushing the previous config, continue if the perm not among the newly created perms | ||
# this is necessary because perm access is mutable; We don't want to destroy modifications made to | ||
# existing permissions | ||
if not created and not flush_previous_config and perm not in [p.name for p in new_perms]: | ||
continue | ||
assert(perm_levels) | ||
perm_access_levels.extend(PermLevel.objects.filter(perm__name=perm, name__in=perm_levels)) | ||
|
||
if flush_previous_config: | ||
perm_access.perm_levels.clear() | ||
perm_access.perm_levels.add(*perm_access_levels) | ||
|
||
def add_individual_access(self, user, perm_name, level_name): | ||
""" | ||
Given a user, a permission name, and the name of the level, add the level in the permission access for | ||
the individual user. | ||
""" | ||
from restraint.models import PermAccess, PermLevel | ||
pa, created = PermAccess.objects.get_or_create( | ||
perm_user_id=user.id, | ||
perm_user_type=ContentType.objects.get_for_model(user) | ||
) | ||
pa.perm_levels.add(PermLevel.objects.get( | ||
perm__name=perm_name, | ||
name=level_name | ||
)) | ||
|
||
def remove_individual_access(self, user, perm_name, level_name): | ||
""" | ||
Given a user, a permission name, and the name of the level, remove the level in the permission access for | ||
the individual user. | ||
""" | ||
from restraint.models import PermAccess, PermLevel | ||
pa = PermAccess.objects.get( | ||
perm_user_id=user.id, | ||
perm_user_type=ContentType.objects.get_for_model(user) | ||
) | ||
pa.perm_levels.remove(PermLevel.objects.get( | ||
perm__name=perm_name, | ||
name=level_name | ||
)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Generated by Django 3.2.12 on 2022-02-20 21:32 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
def update_private_permission_sets(apps, schema_editor): | ||
PermSet = apps.get_model('restraint', 'PermSet') | ||
for perm_set in PermSet.objects.all(): | ||
perm_set.is_private = True | ||
perm_set.save(update_fields=['is_private']) | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('restraint', '0001_initial'), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name='permset', | ||
name='is_private', | ||
field=models.BooleanField(default=False), | ||
), | ||
migrations.RunPython(update_private_permission_sets) | ||
] |
Oops, something went wrong.