Claiming This Task
Before you start working, check the Assignees section. If no one is assigned, leave a comment claiming the issue and assign it to yourself. This prevents duplicate work.
See the Community Wiki for contributing guidelines and git workflow.
Problem
Course creation is currently gated by profile.occupation == "teacher" (via CanCreateCourse permission and the COURSE_CREATION_REQUIRES_TEACHER setting). This has several problems:
- Users must lie about their profession — a student who wants to create a study group course has to change their occupation to "Teacher" on their profile, which is misleading
- No admin control — there's no way for admins to grant course creation rights to specific users without those users changing their own occupation
- Even superusers are blocked — the permission doesn't check
is_superuser, so even admin accounts can't create courses unless their occupation is "teacher"
- All-or-nothing — the
COURSE_CREATION_REQUIRES_TEACHER flag is either on (only "teacher" occupation) or off (everyone), with no middle ground
Requirements
- Create a Django permission group (e.g.
course_creators) that controls who can create courses
- Replace the occupation check in
CanCreateCourse with a group membership check:
- If
COURSE_CREATION_MODE is "open": any authenticated user can create courses
- If
COURSE_CREATION_MODE is "group" (default): only users in the course_creators group (or superusers) can create courses
- Superusers should always be allowed regardless of the mode
- Add a management command (e.g.
manage.py grant_course_creation <username>) to easily add users to the group from the CLI
- The group should be manageable from Django admin — admins can add/remove users via the admin panel
- Deprecate
COURSE_CREATION_REQUIRES_TEACHER — replace with COURSE_CREATION_MODE setting
- Migration: create the permission group in a data migration so it exists on first deploy
Architecture Context
Current implementation:
courses/permissions.py — CanCreateCourse checks profile.occupation == "teacher"
EduLite/settings.py — COURSE_CREATION_REQUIRES_TEACHER = True
courses/views.py — CourseListCreateView uses CanCreateCourse in its permission classes
Approach:
- Use Django's built-in
Group model (django.contrib.auth.models.Group) — no custom models needed
- The permission check becomes
user.groups.filter(name="course_creators").exists() or user.is_superuser
- A data migration creates the group so it's available immediately
Files to be Altered
backend/EduLite/courses/permissions.py — rewrite CanCreateCourse to check group membership
backend/EduLite/EduLite/settings.py — replace COURSE_CREATION_REQUIRES_TEACHER with COURSE_CREATION_MODE
backend/EduLite/courses/management/commands/grant_course_creation.py — new management command
backend/EduLite/courses/migrations/XXXX_create_course_creators_group.py — data migration for group creation
backend/EduLite/courses/tests/test_permissions.py — update existing tests, add group-based tests
backend/EduLite/courses/tests/test_api_course_create.py — update tests for new permission logic
Testing Requirements
- Superuser can always create courses regardless of mode
- In
"group" mode: user in course_creators group can create, user not in group cannot
- In
"open" mode: any authenticated user can create
- Management command adds user to group correctly
- Management command handles non-existent username gracefully
- Existing tests updated to use group-based permissions instead of occupation
- Unauthenticated users still blocked in all modes
Additional Context
This was discovered while building the Course Create/Edit Form Page (#251). A user with admin access couldn't create a course because their profile occupation wasn't set to "teacher" — they had to change their profession on their profile just to use the feature, which defeats the purpose of having an occupation field that reflects reality.
Claiming This Task
Before you start working, check the Assignees section. If no one is assigned, leave a comment claiming the issue and assign it to yourself. This prevents duplicate work.
See the Community Wiki for contributing guidelines and git workflow.
Problem
Course creation is currently gated by
profile.occupation == "teacher"(viaCanCreateCoursepermission and theCOURSE_CREATION_REQUIRES_TEACHERsetting). This has several problems:is_superuser, so even admin accounts can't create courses unless their occupation is "teacher"COURSE_CREATION_REQUIRES_TEACHERflag is either on (only "teacher" occupation) or off (everyone), with no middle groundRequirements
course_creators) that controls who can create coursesCanCreateCoursewith a group membership check:COURSE_CREATION_MODEis"open": any authenticated user can create coursesCOURSE_CREATION_MODEis"group"(default): only users in thecourse_creatorsgroup (or superusers) can create coursesmanage.py grant_course_creation <username>) to easily add users to the group from the CLICOURSE_CREATION_REQUIRES_TEACHER— replace withCOURSE_CREATION_MODEsettingArchitecture Context
Current implementation:
courses/permissions.py—CanCreateCoursechecksprofile.occupation == "teacher"EduLite/settings.py—COURSE_CREATION_REQUIRES_TEACHER = Truecourses/views.py—CourseListCreateViewusesCanCreateCoursein its permission classesApproach:
Groupmodel (django.contrib.auth.models.Group) — no custom models neededuser.groups.filter(name="course_creators").exists() or user.is_superuserFiles to be Altered
backend/EduLite/courses/permissions.py— rewriteCanCreateCourseto check group membershipbackend/EduLite/EduLite/settings.py— replaceCOURSE_CREATION_REQUIRES_TEACHERwithCOURSE_CREATION_MODEbackend/EduLite/courses/management/commands/grant_course_creation.py— new management commandbackend/EduLite/courses/migrations/XXXX_create_course_creators_group.py— data migration for group creationbackend/EduLite/courses/tests/test_permissions.py— update existing tests, add group-based testsbackend/EduLite/courses/tests/test_api_course_create.py— update tests for new permission logicTesting Requirements
"group"mode: user incourse_creatorsgroup can create, user not in group cannot"open"mode: any authenticated user can createAdditional Context
This was discovered while building the Course Create/Edit Form Page (#251). A user with admin access couldn't create a course because their profile occupation wasn't set to "teacher" — they had to change their profession on their profile just to use the feature, which defeats the purpose of having an occupation field that reflects reality.