-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: custom roles and view-user mapping
- Loading branch information
Showing
14 changed files
with
363 additions
and
9 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,63 @@ | ||
"""New roles for FutureX Open edX Extensions.""" | ||
import logging | ||
|
||
from common.djangoapps.student.admin import CourseAccessRoleForm | ||
from common.djangoapps.student.roles import CourseRole, OrgRole, REGISTERED_ACCESS_ROLES, RoleBase | ||
|
||
from futurex_openedx_extensions.helpers.exceptions import FXCodedException, FXExceptionCodes | ||
from futurex_openedx_extensions.helpers.models import ViewAllowedRoles | ||
|
||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
def register_custom_access_role(cls): | ||
""" | ||
Decorator that adds the new access role to the list of registered access roles to be accessible in the Django admin. | ||
Note: roles inheritances is not supported | ||
""" | ||
try: | ||
role_name = cls.ROLE | ||
if role_name in REGISTERED_ACCESS_ROLES: | ||
raise FXCodedException( | ||
code=FXExceptionCodes.CUSTOM_ROLE_DUPLICATE_DECLARATION, | ||
message=f"Trying to register a custom role {role_name} that is already registered!" | ||
) | ||
except AttributeError: | ||
log.exception('Role class %s does not have a ROLE attribute', cls) | ||
except FXCodedException as exc: | ||
log.exception(str(exc)) | ||
else: | ||
REGISTERED_ACCESS_ROLES[role_name] = cls | ||
CourseAccessRoleForm.COURSE_ACCESS_ROLES.append((cls.ROLE, cls.ROLE)) | ||
CourseAccessRoleForm.declared_fields['role'].choices = CourseAccessRoleForm.COURSE_ACCESS_ROLES | ||
ViewAllowedRoles.allowed_role.field.choices = CourseAccessRoleForm.COURSE_ACCESS_ROLES | ||
|
||
return cls | ||
|
||
|
||
@register_custom_access_role | ||
class FXAPIAccessRoleCourse(CourseRole): | ||
"""Course specific access to the FutureX APIs.""" | ||
ROLE = 'fx_api_access' | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(self.ROLE, *args, **kwargs) | ||
|
||
|
||
class FXAPIAccessRoleOrg(OrgRole): | ||
"""Tenant-wide access to the FutureX APIs.""" | ||
ROLE = 'fx_api_access' | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(self.ROLE, *args, **kwargs) | ||
|
||
|
||
@register_custom_access_role | ||
class FXAPIAccessRoleGlobal(RoleBase): | ||
"""Global access to the FutureX APIs.""" | ||
ROLE = 'fx_api_access_global' | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(self.ROLE, *args, **kwargs) |
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
68 changes: 68 additions & 0 deletions
68
futurex_openedx_extensions/helpers/migrations/0005_view_user_mapping.py
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,68 @@ | ||
# Generated by Django 3.2.25 on 2024-11-19 05:51 | ||
|
||
from django.conf import settings | ||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
import simple_history.models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
('fx_helpers', '0004_dataexporttask'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name='historicalviewallowedroles', | ||
name='allowed_role', | ||
field=models.CharField(choices=[('fx_api_access', 'fx_api_access'), ('fx_api_access_global', 'fx_api_access_global')], max_length=255), | ||
), | ||
migrations.AlterField( | ||
model_name='viewallowedroles', | ||
name='allowed_role', | ||
field=models.CharField(choices=[('fx_api_access', 'fx_api_access'), ('fx_api_access_global', 'fx_api_access_global')], max_length=255), | ||
), | ||
migrations.AlterField( | ||
model_name='viewallowedroles', | ||
name='view_name', | ||
field=models.CharField(choices=[('clickhouse_query_fetcher', 'clickhouse_query_fetcher'), ('course_statuses', 'course_statuses'), ('courses_list', 'courses_list'), ('exported_files_data', 'exported_files_data'), ('global_rating', 'global_rating'), ('learner_courses', 'learner_courses'), ('learner_detailed_info', 'learner_detailed_info'), ('learners_list', 'learners_list'), ('learners_with_details_for_course', 'learners_with_details_for_course'), ('my_roles', 'my_roles'), ('total_counts_statistics', 'total_counts_statistics'), ('user_roles', 'user_roles')], max_length=255), | ||
), | ||
migrations.CreateModel( | ||
name='HistoricalViewUserMapping', | ||
fields=[ | ||
('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), | ||
('view_name', models.CharField(max_length=255)), | ||
('enabled', models.BooleanField(default=True)), | ||
('expires_at', models.DateTimeField(blank=True, null=True)), | ||
('history_id', models.AutoField(primary_key=True, serialize=False)), | ||
('history_date', models.DateTimeField()), | ||
('history_change_reason', models.CharField(max_length=100, null=True)), | ||
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), | ||
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), | ||
('user', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), | ||
], | ||
options={ | ||
'verbose_name': 'historical View-User Mapping', | ||
'ordering': ('-history_date', '-history_id'), | ||
'get_latest_by': 'history_date', | ||
}, | ||
bases=(simple_history.models.HistoricalChanges, models.Model), | ||
), | ||
migrations.CreateModel( | ||
name='ViewUserMapping', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('view_name', models.CharField(choices=[('clickhouse_query_fetcher', 'clickhouse_query_fetcher'), ('course_statuses', 'course_statuses'), ('courses_list', 'courses_list'), ('exported_files_data', 'exported_files_data'), ('global_rating', 'global_rating'), ('learner_courses', 'learner_courses'), ('learner_detailed_info', 'learner_detailed_info'), ('learners_list', 'learners_list'), ('learners_with_details_for_course', 'learners_with_details_for_course'), ('my_roles', 'my_roles'), ('total_counts_statistics', 'total_counts_statistics'), ('user_roles', 'user_roles')], max_length=255)), | ||
('enabled', models.BooleanField(default=True)), | ||
('expires_at', models.DateTimeField(blank=True, null=True)), | ||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), | ||
], | ||
options={ | ||
'verbose_name': 'View-User Mapping', | ||
'verbose_name_plural': 'Views-Users Mapping', | ||
'unique_together': {('view_name', 'user')}, | ||
}, | ||
), | ||
] |
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
Oops, something went wrong.