Drop Osztaly.tanev FK; drive class↔tanév via Tanev.osztalyok M2M and gate login on active tanév#5
Merged
Conversation
Copilot created this pull request from a session on behalf of
PstasDev
July 1, 2026 11:03
View session
PstasDev
marked this pull request as ready for review
July 1, 2026 11:03
There was a problem hiding this comment.
Pull request overview
This PR removes the ambiguous Osztaly.tanev FK and standardizes the class↔school-year relationship on Tanev.osztalyok (M2M), while also enforcing “active tanév” access control during login/JWT authentication.
Changes:
- Replaces
Osztaly.tanevFK usage across APIs/imports/admin withTanev.osztalyokM2M (+ “latest tanév” compatibility accessors/fields). - Adds a data migration to copy existing FK links into the M2M before dropping the FK column.
- Gates
/loginand JWT token auth based on whether a student’s class belongs to the active tanév (with teacher/admin exemptions).
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| import_users.py | Updates class creation to attach Osztaly to Tanev via M2M. |
| backend/api_modules/user_import.py | Computes tanév label from osztaly.tanevek instead of FK. |
| backend/api_modules/user_import_utils.py | Same M2M-based class attachment; updates docstring. |
| backend/api_modules/sync.py | Adds tanev_ids and switches class/profile query optimization from FK to M2M prefetch. |
| backend/api_modules/configuration_wizard.py | Creates classes without FK; links to current tanév via M2M. |
| backend/api_modules/auth.py | Adds is_user_allowed_for_current_tanev() and enforces it in login + JWT auth. |
| backend/api_modules/academic.py | Exposes tanevek list; updates create/update and fetches to use M2M. |
| api/resources.py | Exports computed tanév display based on latest M2M-linked tanév. |
| api/models.py | Removes FK field; __str__ and compatibility tanev property now use M2M and active tanév. |
| api/migrations/0035_remove_osztaly_tanev_field.py | Copies FK relationship into M2M then drops the FK column. |
| api/management/commands/demonstration.py | Demo data uses M2M linking instead of FK defaults. |
| api/admin.py | Admin listing/filtering updated to use reverse tanevek and computed display. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+16
to
+31
| migrations.RunPython( | ||
| code=lambda apps, schema_editor: _copy_osztaly_tanev_to_m2m(apps), | ||
| reverse_code=migrations.RunPython.noop, | ||
| ), | ||
| migrations.RemoveField( | ||
| model_name='osztaly', | ||
| name='tanev', | ||
| ), | ||
| ] | ||
|
|
||
|
|
||
| def _copy_osztaly_tanev_to_m2m(apps): | ||
| Osztaly = apps.get_model('api', 'Osztaly') | ||
| for osztaly in Osztaly.objects.exclude(tanev__isnull=True): | ||
| osztaly.tanev.osztalyok.add(osztaly) | ||
|
|
Comment on lines
+165
to
+169
| try: | ||
| from api.models import Profile, Tanev, Osztaly | ||
| except Exception as e: # pragma: no cover - very unlikely | ||
| print(f"is_user_allowed_for_current_tanev import error: {e}") | ||
| return True, "" |
Comment on lines
435
to
+450
| def __str__(self): | ||
| # A megjelenített osztálynév mindig az aktuálisan aktív tanév alapján | ||
| # kerül kiszámításra (a Tanev.osztalyok M2M az igazságforrás arra, hogy | ||
| # egy osztály melyik tanévben aktív). | ||
| return self.get_current_year_name() | ||
|
|
||
| def get_current_year_name(self, reference_tanev=None): | ||
| """Az osztály neve egy adott tanévhez viszonyítva. | ||
|
|
||
| Ha nincs megadva ``reference_tanev``, akkor az aktuálisan aktív tanévet | ||
| használjuk. Ha nincs aktív tanév egyáltalán (pl. nyári szünet vagy | ||
| friss telepítés), akkor a mai dátum alapján próbálunk visszaesni egy | ||
| naptári becslésre, hogy a régi viselkedést megőrizzük. | ||
| """ | ||
| if reference_tanev is None: | ||
| reference_tanev = Tanev.get_active() |
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Osztaly.tanevduplicated theTanev.osztalyokM2M and made multi-tanév handling ambiguous. Class names should be computed against the currently activeTanev, and non-teacher/admin users outside the active tanév should not be able to log in.Model & migration
Osztaly.tanevFK;Tanev.osztalyokM2M is now the single source of truth.Osztaly.__str__delegates toget_current_year_name(), which is anchored onTanev.get_active()(calendar-based fallback preserved only when no active tanév exists).Osztaly.tanevproperty returns the latest linkedTanevvia the reversetanevekrelation for compatibility with existing serializer code.0035_remove_osztaly_tanev_fieldcopies each existing FK link into the M2M viaRunPythonbefore dropping the column so no data is lost.API surface (multi-tanév aware)
academic.OsztalySchema/OsztalyWithTeachersSchemaexpose bothtanev(latest) andtanevek(full list) so the frontend can filter/group per tanév.sync.OsztalySchemaaddstanev_ids: List[int].tanev_id, but now attach viatanev.add_osztaly(osztaly)instead of writing an FK.Osztaly.objects.select_related('tanev')/osztaly__tanevswapped forprefetch_related('tanevek')/osztaly__tanevek.academic.py,sync.py,user_import.py,user_import_utils.py,configuration_wizard.py,import_users.py,demonstration.py, admin, resources.Login access control
backend/api_modules/auth.pyaddsis_user_allowed_for_current_tanev(user)used by both/login(returns 403 with a Hungarian message) andJWTAuth.authenticate(so pre-existing tokens can't bypass it). A user is denied iff:Tanev, andProfile, andis_admin, not anosztályfőnök, not Djangois_staff/is_superuser, andosztalyis not inactive_tanev.osztalyok.