Skip to content

Commit 9e3b0c6

Browse files
committed
feat!: new enrollment by domain feature
1 parent da602f9 commit 9e3b0c6

File tree

21 files changed

+1220
-39
lines changed

21 files changed

+1220
-39
lines changed

nau_openedx_extensions/admin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
from __future__ import absolute_import, unicode_literals
55

66
from nau_openedx_extensions.custom_registration_form.admin import * # pylint: disable=wildcard-import
7+
from nau_openedx_extensions.enrollment_by_domain.admin import * # pylint: disable=wildcard-import
78
from nau_openedx_extensions.student.admin import * # pylint: disable=wildcard-import

nau_openedx_extensions/apps.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ def ready(self):
4242
"""
4343
Method to perform actions after apps registry is ended
4444
"""
45+
4546
from nau_openedx_extensions import signals # pylint: disable=import-outside-toplevel,unused-import # noqa
Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
# Enrollment by Domain Filter
2+
3+
This OpenEdX extension allows restricting course enrollment based on user email domains. It integrates with the `openedx-filters` framework to automatically validate domains during the enrollment process.
4+
5+
## Features
6+
7+
- **Automatic Domain Filtering**: Blocks enrollment for users whose email domains are not in the allowed list
8+
- **Course-Level Configuration**: Enable/disable filtering per course via Advanced Settings
9+
- **Simple Domain Management**: Import domains via command or manage through Django Admin
10+
- **Custom Error Messages**: Configure personalized error messages at course or list level
11+
- **Instructor Override**: Preserves compatibility with manual enrollment allowlists
12+
13+
## Quick Start
14+
15+
16+
### 1. Configure OpenEdX Filters
17+
Add to your Tutor plugin configuration:
18+
19+
```python
20+
from tutor import hooks
21+
22+
hooks.Filters.ENV_PATCHES.add_item(
23+
(
24+
"openedx-lms-common-settings",
25+
"""
26+
OPEN_EDX_FILTERS_CONFIG = {
27+
"org.openedx.learning.course.enrollment.started.v1": {
28+
"fail_silently": False,
29+
"pipeline": [
30+
"nau_openedx_extensions.enrollment_by_domain.domain_filter.FilterEnrollmentByAllowedList"
31+
]
32+
}
33+
}
34+
"""
35+
)
36+
)
37+
```
38+
39+
40+
### 2. Create Domain List
41+
```bash
42+
# Basic import with minimal options
43+
python manage.py lms import_enrollment_domains example_domains.txt university-partners
44+
```
45+
> [!NOTE] You must use the files relative or absolute path, example: ../extra/nau-openedx-extensions/nau_openedx_extensions/enrollment_by_domain/example_domains.txt
46+
47+
48+
### 3. Configure Course
49+
In **Studio****Advanced Settings****Other Course Settings**:
50+
```json
51+
{
52+
"filter_enrollment_allowed_list_code": "university-partners"
53+
}
54+
```
55+
56+
## Domain Management
57+
58+
### Import Command Syntax
59+
```bash
60+
python manage.py lms import_enrollment_domains <file.txt> <list-code> [options]
61+
```
62+
63+
### Command Options
64+
65+
| Option | Description |
66+
|--------|-------------|
67+
| `--description "text"` | List description |
68+
| `--custom-message "text"` | Custom error message |
69+
70+
### Domain File Format
71+
```txt
72+
# University domains (comments start with #)
73+
university.edu
74+
student.university.edu
75+
faculty.university.edu
76+
77+
# Partner institutions
78+
partner.org
79+
collaborator.ac.uk
80+
alumni.university.edu
81+
82+
# Empty lines and comments are ignored
83+
```
84+
85+
## Usage Examples
86+
87+
### Basic Usage
88+
```bash
89+
# Simple domain import
90+
python manage.py lms import_enrollment_domains domains.txt list-code
91+
92+
# With description
93+
python manage.py lms import_enrollment_domains domains.txt list-code --description "Partner universities"
94+
95+
# With custom error message
96+
python manage.py lms import_enrollment_domains domains.txt list-code --custom-message "Contact admissions@university.edu for access"
97+
98+
# Full configuration
99+
python manage.py lms import_enrollment_domains domains.txt list-code --description "Partner universities" --custom-message "Only partner university students can enroll"
100+
```
101+
102+
### Example 1: University Partners
103+
```bash
104+
# txt file
105+
# Main universities
106+
university.edu
107+
partneruniv.edu
108+
college.edu
109+
110+
# Student domains
111+
students.university.edu
112+
alumni.university.edu
113+
114+
115+
# Import domains
116+
python manage.py lms import_enrollment_domains university_domains.txt university-partners --description "Partner universities" --custom-message "Only students from partner universities can enroll. Contact admissions@university.edu for assistance."
117+
```
118+
119+
**Course Configuration in Studio:**
120+
```json
121+
{
122+
"filter_enrollment_allowed_list_code": "university-partners"
123+
}
124+
```
125+
126+
### Example 2: Corporate Training Program
127+
```bash
128+
# Create corporate domains .txt file
129+
# Primary companies
130+
company.com
131+
corporation.org
132+
business.net
133+
134+
# Subsidiaries
135+
subsidiary1.company.com
136+
subsidiary2.company.com
137+
138+
139+
# Import corporate domains
140+
python manage.py lms import_enrollment_domains corporate_domains.txt corporate-training --description "Corporate training participants" --custom-message "This course is restricted to employees of partner companies."
141+
```
142+
143+
### Example 3: Multiple Domain Lists
144+
```bash
145+
# University partners list
146+
python manage.py lms import_enrollment_domains university_domains.txt uni-partners --description "University partners"
147+
148+
# Corporate partners list
149+
python manage.py lms import_enrollment_domains corporate_domains.txt corp-partners --description "Corporate partners"
150+
151+
# Alumni program list
152+
python manage.py lms import_enrollment_domains alumni_domains.txt alumni-program --description "Alumni program participants"
153+
```
154+
155+
### Example 4: Adding More Domains
156+
```bash
157+
# Add new domains to existing list
158+
python manage.py lms import_enrollment_domains additional_partners.txt university-partners
159+
160+
# Update existing list with new description and message
161+
python manage.py lms import_enrollment_domains updated_domains.txt university-partners --description "Updated partner list" --custom-message "New enrollment policy applies"
162+
```
163+
164+
**Note**: The command only adds new domains. Existing domains are preserved and duplicates are automatically skipped.
165+
166+
## Course Configuration
167+
168+
### Enable Filter for a Course
169+
170+
1. Go to **Studio****Settings****Advanced Settings**
171+
2. Find **"Other Course Settings"** or add new field
172+
3. Add configuration:
173+
174+
```json
175+
{
176+
"filter_enrollment_allowed_list_code": "your-list-code"
177+
}
178+
```
179+
180+
### Custom Error Messages
181+
182+
**Option 1: List-level message (affects all courses using this list)**
183+
```bash
184+
python manage.py lms import_enrollment_domains domains.txt my-list --custom-message "Contact support@example.com for enrollment assistance."
185+
```
186+
187+
**Option 2: Course-level message (overrides list message for this course)**
188+
```json
189+
{
190+
"filter_enrollment_allowed_list_code": "my-list",
191+
"filter_enrollment_by_domain_custom_exception_message": "This course is restricted to university partners only."
192+
}
193+
```
194+
195+
If the custom exception message is not defined, it will use a default message
196+
197+
### Priority Order for Error Messages
198+
1. **Course-level custom message** (from Advanced Settings)
199+
2. **List-level custom message** (from import command or Django admin)
200+
3. **Default message**: "You can't enroll on this course because your email domain is not allowed. If you think this is an error, contact the course support."
201+
202+
203+
## Command Output Examples
204+
205+
### New List Creation
206+
```
207+
============================================================
208+
IMPORT SUMMARY: university-partners
209+
============================================================
210+
Created new allowed list
211+
212+
Domain Statistics:
213+
Domains in file: 8
214+
Domains to add: 8
215+
Domains unchanged: 0
216+
Import completed successfully!
217+
Added: 8 domains
218+
Total domains in list: 8
219+
============================================================
220+
```
221+
222+
### Adding to Existing List
223+
```
224+
============================================================
225+
IMPORT SUMMARY: university-partners
226+
============================================================
227+
Found existing allowed list
228+
229+
Domain Statistics:
230+
Domains in file: 10
231+
Domains to add: 2
232+
Domains unchanged: 8
233+
234+
Import completed successfully!
235+
Added: 2 domains
236+
Total domains in list: 10
237+
============================================================
238+
```
239+
240+
### No Changes Needed
241+
```
242+
============================================================
243+
IMPORT SUMMARY: university-partners
244+
============================================================
245+
Found existing allowed list
246+
247+
Domain Statistics:
248+
Domains in file: 8
249+
Domains to add: 0
250+
Domains unchanged: 8
251+
252+
No changes needed
253+
All domains already in list
254+
Total domains in list: 8
255+
============================================================
256+
```
257+
258+
## How It Works
259+
260+
### Filter Activation
261+
1. **User attempts enrollment** in a course
262+
2. **OpenEdX Event** `org.openedx.learning.course.enrollment.started.v1`
263+
3. **Filter checks** if course has `filter_enrollment_allowed_list_code` configured
264+
4. **If configured**, validates user's email domain against the allowed list
265+
5. **Blocks enrollment** if domain is not allowed
266+
6. **Shows custom message** to the user
267+
268+
269+
270+
## Django Admin Management
271+
272+
Access domain management through Django Admin:
273+
274+
1. Go to `/admin/`
275+
2. Navigate to **"Enrollment By Domain"** section
276+
3. Manage **"Enrollment Allowed Lists"** and **"Enrollment Allowed Domains"**
277+
278+
## Best Practices
279+
280+
1. **Use descriptive list codes** (`university-partners`, not `list1`)
281+
2. **Set custom messages** for better user experience
282+
3. **Test thoroughly** after configuration changes
283+

nau_openedx_extensions/enrollment_by_domain/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)