diff --git a/apikey/__init__.py b/api/__init__.py similarity index 100% rename from apikey/__init__.py rename to api/__init__.py diff --git a/apikey/admin.py b/api/admin.py similarity index 95% rename from apikey/admin.py rename to api/admin.py index ef6a247c..611bdba0 100644 --- a/apikey/admin.py +++ b/api/admin.py @@ -3,8 +3,8 @@ from django.db.models import QuerySet from django.http import HttpRequest from django.utils.translation import gettext_lazy as _ -from apikey.hashers import generate_key -from apikey.models import ApiClient, ApiKey +from api.hashers import generate_key +from api.models import ApiClient, ApiKey @admin.register(ApiClient) diff --git a/apikey/apps.py b/api/apps.py similarity index 64% rename from apikey/apps.py rename to api/apps.py index 4ce409b2..878e7d54 100644 --- a/apikey/apps.py +++ b/api/apps.py @@ -1,6 +1,6 @@ from django.apps import AppConfig -class ApikeyConfig(AppConfig): +class ApiConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "apikey" + name = "api" diff --git a/apikey/auth.py b/api/auth.py similarity index 87% rename from apikey/auth.py rename to api/auth.py index d1489f7f..787234a6 100644 --- a/apikey/auth.py +++ b/api/auth.py @@ -1,8 +1,8 @@ from django.http import HttpRequest from ninja.security import APIKeyHeader -from apikey.hashers import get_hasher -from apikey.models import ApiClient, ApiKey +from api.hashers import get_hasher +from api.models import ApiClient, ApiKey class ApiKeyAuth(APIKeyHeader): diff --git a/apikey/hashers.py b/api/hashers.py similarity index 100% rename from apikey/hashers.py rename to api/hashers.py diff --git a/apikey/migrations/0001_initial.py b/api/migrations/0001_initial.py similarity index 98% rename from apikey/migrations/0001_initial.py rename to api/migrations/0001_initial.py index b416b749..4ebfe9d4 100644 --- a/apikey/migrations/0001_initial.py +++ b/api/migrations/0001_initial.py @@ -99,7 +99,7 @@ class Migration(migrations.Migration): models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="api_keys", - to="apikey.apiclient", + to="api.apiclient", verbose_name="api client", ), ), diff --git a/apikey/migrations/__init__.py b/api/migrations/__init__.py similarity index 100% rename from apikey/migrations/__init__.py rename to api/migrations/__init__.py diff --git a/apikey/models.py b/api/models.py similarity index 100% rename from apikey/models.py rename to api/models.py diff --git a/core/auth/api_permissions.py b/api/permissions.py similarity index 88% rename from core/auth/api_permissions.py rename to api/permissions.py index 73f9fa84..f371910b 100644 --- a/core/auth/api_permissions.py +++ b/api/permissions.py @@ -39,7 +39,7 @@ Example: import operator from functools import reduce -from typing import Any +from typing import Any, Callable from django.contrib.auth.models import Permission from django.http import HttpRequest @@ -67,21 +67,26 @@ class HasPerm(BasePermission): Example: ```python - # this route will require both permissions - @route.put("/foo", permissions=[HasPerm(["foo.change_foo", "foo.add_foo"])] - def foo(self): ... + @api_controller("/foo") + class FooController(ControllerBase): + # this route will require both permissions + @route.put("/foo", permissions=[HasPerm(["foo.change_foo", "foo.add_foo"])] + def foo(self): ... - # This route will require at least one of the perm, - # but it's not mandatory to have all of them - @route.put( - "/bar", - permissions=[HasPerm(["foo.change_bar", "foo.add_bar"], op=operator.or_)], - ) - def bar(self): ... + # This route will require at least one of the perm, + # but it's not mandatory to have all of them + @route.put( + "/bar", + permissions=[HasPerm(["foo.change_bar", "foo.add_bar"], op=operator.or_)], + ) + def bar(self): ... + ``` """ def __init__( - self, perms: str | Permission | list[str | Permission], op=operator.and_ + self, + perms: str | Permission | list[str | Permission], + op: Callable[[bool, bool], bool] = operator.and_, ): """ Args: @@ -103,7 +108,7 @@ class HasPerm(BasePermission): # If not, this authentication has not been done, but the user may # still be implicitly authenticated through AuthenticationMiddleware user = request.auth if hasattr(request, "auth") else request.user - # `user` may either be a `core.User` or an `apikey.ApiClient` ; + # `user` may either be a `core.User` or an `api.ApiClient` ; # they are not the same model, but they both implement the `has_perm` method return reduce(self._operator, (user.has_perm(p) for p in self._perms)) diff --git a/api/tests/__init__.py b/api/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apikey/tests.py b/api/tests/test_api_key.py similarity index 85% rename from apikey/tests.py rename to api/tests/test_api_key.py index a971af2d..4fad18d3 100644 --- a/apikey/tests.py +++ b/api/tests/test_api_key.py @@ -2,9 +2,9 @@ import pytest from django.test import RequestFactory from model_bakery import baker -from apikey.auth import ApiKeyAuth -from apikey.hashers import generate_key -from apikey.models import ApiClient, ApiKey +from api.auth import ApiKeyAuth +from api.hashers import generate_key +from api.models import ApiClient, ApiKey @pytest.mark.django_db diff --git a/club/api.py b/club/api.py index decdf8f8..ef46e4c7 100644 --- a/club/api.py +++ b/club/api.py @@ -6,10 +6,10 @@ from ninja_extra import ControllerBase, api_controller, paginate, route from ninja_extra.pagination import PageNumberPaginationExtra from ninja_extra.schemas import PaginatedResponseSchema -from apikey.auth import ApiKeyAuth +from api.auth import ApiKeyAuth +from api.permissions import CanAccessLookup, HasPerm from club.models import Club from club.schemas import ClubSchema, SimpleClubSchema -from core.auth.api_permissions import CanAccessLookup, HasPerm @api_controller("/club") diff --git a/com/api.py b/com/api.py index 9dd70606..27977e2b 100644 --- a/com/api.py +++ b/com/api.py @@ -7,10 +7,10 @@ from ninja_extra.pagination import PageNumberPaginationExtra from ninja_extra.permissions import IsAuthenticated from ninja_extra.schemas import PaginatedResponseSchema +from api.permissions import HasPerm from com.ics_calendar import IcsCalendar from com.models import News, NewsDate from com.schemas import NewsDateFilterSchema, NewsDateSchema -from core.auth.api_permissions import HasPerm from core.views.files import send_raw_file diff --git a/com/models.py b/com/models.py index c7e66515..c0a11ac3 100644 --- a/com/models.py +++ b/com/models.py @@ -191,7 +191,7 @@ class NewsDateQuerySet(models.QuerySet): class NewsDate(models.Model): """A date associated with news. - A [News][] can have multiple dates, for example if it is a recurring event. + A [News][com.models.News] can have multiple dates, for example if it is a recurring event. """ news = models.ForeignKey( diff --git a/core/api.py b/core/api.py index bd74875b..06b32989 100644 --- a/core/api.py +++ b/core/api.py @@ -11,9 +11,9 @@ from ninja_extra.exceptions import PermissionDenied from ninja_extra.pagination import PageNumberPaginationExtra from ninja_extra.schemas import PaginatedResponseSchema -from apikey.auth import ApiKeyAuth +from api.auth import ApiKeyAuth +from api.permissions import CanAccessLookup, CanView, HasPerm from club.models import Mailing -from core.auth.api_permissions import CanAccessLookup, CanView, HasPerm from core.models import Group, QuickUploadImage, SithFile, User from core.schemas import ( FamilyGodfatherSchema, diff --git a/counter/api.py b/counter/api.py index 11bf56c9..c7bcb540 100644 --- a/counter/api.py +++ b/counter/api.py @@ -21,8 +21,8 @@ from ninja_extra import ControllerBase, api_controller, paginate, route from ninja_extra.pagination import PageNumberPaginationExtra from ninja_extra.schemas import PaginatedResponseSchema -from apikey.auth import ApiKeyAuth -from core.auth.api_permissions import CanAccessLookup, CanView, IsInGroup, IsRoot +from api.auth import ApiKeyAuth +from api.permissions import CanAccessLookup, CanView, IsInGroup, IsRoot from counter.models import Counter, Product, ProductType from counter.schemas import ( CounterFilterSchema, diff --git a/counter/models.py b/counter/models.py index 3515e081..0f46176b 100644 --- a/counter/models.py +++ b/counter/models.py @@ -61,7 +61,7 @@ class CustomerQuerySet(models.QuerySet): Returns: The number of updated rows. - Warnings: + Warning: The execution time of this query grows really quickly. When updating 500 customers, it may take around a second. If you try to update all customers at once, the execution time diff --git a/docs/reference/apikey/auth.md b/docs/reference/api/auth.md similarity index 86% rename from docs/reference/apikey/auth.md rename to docs/reference/api/auth.md index f6261037..764dd318 100644 --- a/docs/reference/apikey/auth.md +++ b/docs/reference/api/auth.md @@ -1,4 +1,4 @@ -::: apikey.auth +::: api.auth handler: python options: heading_level: 3 diff --git a/docs/reference/apikey/hashers.md b/docs/reference/api/hashers.md similarity index 89% rename from docs/reference/apikey/hashers.md rename to docs/reference/api/hashers.md index eb728802..91c420b2 100644 --- a/docs/reference/apikey/hashers.md +++ b/docs/reference/api/hashers.md @@ -1,4 +1,4 @@ -::: apikey.hashers +::: api.hashers handler: python options: heading_level: 3 diff --git a/docs/reference/apikey/models.md b/docs/reference/api/models.md similarity index 88% rename from docs/reference/apikey/models.md rename to docs/reference/api/models.md index 52da58df..dbf2676b 100644 --- a/docs/reference/apikey/models.md +++ b/docs/reference/api/models.md @@ -1,4 +1,4 @@ -::: apikey.auth +::: api.auth handler: python options: heading_level: 3 diff --git a/docs/reference/api/perms.md b/docs/reference/api/perms.md new file mode 100644 index 00000000..c481bd28 --- /dev/null +++ b/docs/reference/api/perms.md @@ -0,0 +1,4 @@ +::: api.permissions + handler: python + options: + heading_level: 3 \ No newline at end of file diff --git a/docs/reference/core/auth.md b/docs/reference/core/auth.md index ade23f49..4226bb2c 100644 --- a/docs/reference/core/auth.md +++ b/docs/reference/core/auth.md @@ -20,13 +20,6 @@ - CanCreateMixin - CanEditMixin - CanViewMixin + - CanEditPropMixin - FormerSubscriberMixin - PermissionOrAuthorRequiredMixin - - -## API Permissions - -::: core.auth.api_permissions - handler: python - options: - heading_level: 3 \ No newline at end of file diff --git a/docs/tutorial/api/dev.md b/docs/tutorial/api/dev.md index 4d2de4e8..165d605f 100644 --- a/docs/tutorial/api/dev.md +++ b/docs/tutorial/api/dev.md @@ -4,6 +4,25 @@ Ce sont des librairies relativement simples et qui présentent l'immense avantage d'offrir des mécanismes de validation et de sérialisation de données à la fois simples et expressifs. +## Dossiers et fichiers + +L'API possède une application (`api`) +à la racine du projet, contenant des utilitaires +et de la configuration partagée par toutes les autres applications. +C'est la pièce centrale de notre API, mais ce n'est pas là que +vous trouverez les routes de l'API. + +Les routes en elles-mêmes sont contenues dans les autres applications, +de manière thématiques : +les routes liées aux clubs sont dans `club`, les routes liées +aux photos dans `sas` et ainsi de suite. + +Les fichiers liés à l'API dans chaque application sont +`schemas.py` et `api.py`. +`schemas.py` contient les schémas de validation de données +et `api.py` contient les contrôleurs de l'API. + + ## Schéma de données Le cœur de django-ninja étant sa validation de données grâce à Pydantic, @@ -33,7 +52,7 @@ La plus grande partie des routes de l'API utilisent la méthode par cookie de se Pour placer une route d'API derrière l'une de ces méthodes (ou bien les deux), utilisez l'attribut `auth` et les classes `SessionAuth` et -[`ApiKeyAuth`][apikey.auth.ApiKeyAuth]. +[`ApiKeyAuth`][api.auth.ApiKeyAuth]. !!!example diff --git a/docs/tutorial/perms.md b/docs/tutorial/perms.md index c23ca25f..4594c81e 100644 --- a/docs/tutorial/perms.md +++ b/docs/tutorial/perms.md @@ -606,4 +606,4 @@ vous ne devriez pas être perdu, étant donné que le système de permissions de l'API utilise des noms assez similaires : `IsInGroup`, `IsRoot`, `IsSubscriber`... Vous pouvez trouver des exemples d'utilisation de ce système -dans [cette partie](../reference/core/api_permissions.md). +dans [cette partie](../reference/api/perms.md). diff --git a/docs/tutorial/structure.md b/docs/tutorial/structure.md index b687d25b..1ba8a603 100644 --- a/docs/tutorial/structure.md +++ b/docs/tutorial/structure.md @@ -24,64 +24,68 @@ sith/ ├── .github/ │ ├── actions/ (1) │ └── workflows/ (2) -├── club/ (3) +├── api/ (3) │ └── ... -├── com/ (4) +├── antispam/ (4) │ └── ... -├── core/ (5) +├── club/ (5) │ └── ... -├── counter/ (6) +├── com/ (6) │ └── ... -├── docs/ (7) +├── core/ (7) │ └── ... -├── eboutic/ (8) +├── counter/ (8) │ └── ... -├── election/ (9) +├── docs/ (9) │ └── ... -├── forum/ (10) +├── eboutic/ (10) │ └── ... -├── galaxy/ (11) +├── election/ (11) │ └── ... -├── launderette/ (12) +├── forum/ (12) │ └── ... -├── locale/ (13) +├── galaxy/ (13) │ └── ... -├── matmat/ (14) +├── launderette/ (14) │ └── ... -├── pedagogy/ (15) +├── locale/ (15) │ └── ... -├── rootplace/ (16) +├── matmat/ (16) │ └── ... -├── sas/ (17) +├── pedagogy/ (17) │ └── ... -├── sith/ (18) +├── rootplace/ (18) │ └── ... -├── subscription/ (19) +├── sas/ (19) │ └── ... -├── trombi/ (20) +├── sith/ (20) │ └── ... -├── antispam/ (21) +├── subscription/ (21) │ └── ... -├── staticfiles/ (22) +├── trombi/ (22) │ └── ... -├── processes/ (23) +├── antispam/ (23) +│ └── ... +├── staticfiles/ (24) +│ └── ... +├── processes/ (25) │ └── ... │ -├── .coveragerc (24) -├── .envrc (25) +├── .coveragerc (26) +├── .envrc (27) ├── .gitattributes ├── .gitignore ├── .mailmap -├── .env (26) -├── .env.example (27) -├── manage.py (28) -├── mkdocs.yml (29) +├── .env (28) +├── .env.example (29) +├── manage.py (30) +├── mkdocs.yml (31) ├── uv.lock -├── pyproject.toml (30) -├── .venv/ (31) -├── .python-version (32) -├── Procfile.static (33) -├── Procfile.service (34) +├── pyproject.toml (32) +├── .venv/ (33) +├── .python-version (34) +├── Procfile.static (35) +├── Procfile.service (36) └── README.md ``` @@ -94,54 +98,56 @@ sith/ des workflows Github. Par exemple, le workflow `docs.yml` compile et publie la documentation à chaque push sur la branche `master`. -3. Application de gestion des clubs et de leurs membres. -4. Application contenant les fonctionnalités +3. Application avec la configuration de l'API +4. Application contenant des utilitaires pour bloquer le spam et les bots +5. Application de gestion des clubs et de leurs membres. +6. Application contenant les fonctionnalités destinées aux responsables communication de l'AE. -5. Application contenant la modélisation centrale du site. +7. Application contenant la modélisation centrale du site. On en reparle plus loin sur cette page. -6. Application de gestion des comptoirs, des permanences +8. Application de gestion des comptoirs, des permanences sur ces comptoirs et des transactions qui y sont effectuées. -7. Dossier contenant la documentation. -8. Application de gestion de la boutique en ligne. -9. Application de gestion des élections. -10. Application de gestion du forum -11. Application de gestion de la galaxie ; la galaxie +9. Dossier contenant la documentation. +10. Application de gestion de la boutique en ligne. +11. Application de gestion des élections. +12. Application de gestion du forum +13. Application de gestion de la galaxie ; la galaxie est un graphe des niveaux de proximité entre les différents étudiants. -12. Gestion des machines à laver de l'AE -13. Dossier contenant les fichiers de traduction. -14. Fonctionnalités de recherche d'utilisateurs. -15. Le guide des UEs du site, sur lequel les utilisateurs +14. Gestion des machines à laver de l'AE +15. Dossier contenant les fichiers de traduction. +16. Fonctionnalités de recherche d'utilisateurs. +17. Le guide des UEs du site, sur lequel les utilisateurs peuvent également laisser leurs avis. -16. Fonctionnalités utiles aux utilisateurs root. -17. Le SAS, où l'on trouve toutes les photos de l'AE. -18. Application principale du projet, contenant sa configuration. -19. Gestion des cotisations des utilisateurs du site. -20. Outil pour faciliter la fabrication des trombinoscopes de promo. -21. Fonctionnalités pour gérer le spam. -22. Gestion des statics du site. Override le système de statics de Django. +18. Fonctionnalités utiles aux utilisateurs root. +19. Le SAS, où l'on trouve toutes les photos de l'AE. +20. Application principale du projet, contenant sa configuration. +21. Gestion des cotisations des utilisateurs du site. +22. Outil pour faciliter la fabrication des trombinoscopes de promo. +23. Fonctionnalités pour gérer le spam. +24. Gestion des statics du site. Override le système de statics de Django. Ajoute l'intégration du scss et du bundler js de manière transparente pour l'utilisateur. -23. Module de gestion des services externes. +25. Module de gestion des services externes. Offre une API simple pour utiliser les fichiers `Procfile.*`. -24. Fichier de configuration de coverage. -25. Fichier de configuration de direnv. -26. Contient les variables d'environnement, qui sont susceptibles +26. Fichier de configuration de coverage. +27. Fichier de configuration de direnv. +28. Contient les variables d'environnement, qui sont susceptibles de varier d'une machine à l'autre. -27. Contient des valeurs par défaut pour le `.env` +29. Contient des valeurs par défaut pour le `.env` pouvant convenir à un environnment de développement local -28. Fichier généré automatiquement par Django. C'est lui +30. Fichier généré automatiquement par Django. C'est lui qui permet d'appeler des commandes de gestion du projet avec la syntaxe `python ./manage.py ` -29. Le fichier de configuration de la documentation, +31. Le fichier de configuration de la documentation, avec ses plugins et sa table des matières. -30. Le fichier où sont déclarés les dépendances et la configuration +32. Le fichier où sont déclarés les dépendances et la configuration de certaines d'entre elles. -31. Dossier d'environnement virtuel généré par uv -32. Fichier qui contrôle quelle version de python utiliser pour le projet -33. Fichier qui contrôle les commandes à lancer pour gérer la compilation +33. Dossier d'environnement virtuel généré par uv +34. Fichier qui contrôle quelle version de python utiliser pour le projet +35. Fichier qui contrôle les commandes à lancer pour gérer la compilation automatique des static et autres services nécessaires à la command runserver. -34. Fichier qui contrôle les services tiers nécessaires au fonctionnement +36. Fichier qui contrôle les services tiers nécessaires au fonctionnement du Sith tel que redis. ## L'application principale diff --git a/eboutic/api.py b/eboutic/api.py index 2041fb87..c44a8cc9 100644 --- a/eboutic/api.py +++ b/eboutic/api.py @@ -1,7 +1,7 @@ from ninja_extra import ControllerBase, api_controller, route from ninja_extra.exceptions import NotFound -from core.auth.api_permissions import CanView +from api.permissions import CanView from counter.models import BillingInfo from eboutic.models import Basket diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index c8578923..00709f8f 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-01 11:06+0200\n" +"POT-Creation-Date: 2025-06-04 09:33+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Maréchal \n" @@ -35,7 +35,7 @@ msgstr "" "True si gardé à jour par le biais d'un fournisseur externe de domains " "toxics, False sinon" -#: apikey/admin.py +#: api/admin.py #, python-format msgid "" "The API key for %(name)s is: %(key)s. Please store it somewhere safe: you " @@ -44,57 +44,56 @@ msgstr "" "La clef d'API pour %(name)s est : %(key)s. Gardez-là dans un emplacement " "sûr : vous ne pourrez pas la revoir à nouveau." -#: apikey/admin.py +#: api/admin.py msgid "Revoke selected API keys" msgstr "Révoquer les clefs d'API sélectionnées" -#: apikey/models.py club/models.py com/models.py counter/models.py -#: forum/models.py launderette/models.py +#: api/models.py club/models.py com/models.py counter/models.py forum/models.py msgid "name" msgstr "nom" -#: apikey/models.py core/models.py +#: api/models.py core/models.py msgid "owner" msgstr "propriétaire" -#: apikey/models.py core/models.py +#: api/models.py core/models.py msgid "groups" msgstr "groupes" -#: apikey/models.py +#: api/models.py msgid "client permissions" msgstr "permissions du client" -#: apikey/models.py +#: api/models.py msgid "Specific permissions for this api client." msgstr "Permissions spécifiques pour ce client d'API" -#: apikey/models.py +#: api/models.py msgid "api client" msgstr "client d'api" -#: apikey/models.py +#: api/models.py msgid "api clients" msgstr "clients d'api" -#: apikey/models.py +#: api/models.py msgid "prefix" msgstr "préfixe" -#: apikey/models.py +#: api/models.py msgid "hashed key" msgstr "hash de la clef" -#: apikey/models.py +#: api/models.py msgctxt "api key" msgid "revoked" msgstr "révoquée" -#: apikey/models.py +#: api/models.py msgid "api key" msgstr "clef d'api" -#: apikey/models.py +#: api/models.py msgid "api keys" msgstr "clefs d'api" @@ -118,8 +117,7 @@ msgstr "S'abonner" msgid "Remove" msgstr "Retirer" -#: club/forms.py launderette/views.py -#: pedagogy/templates/pedagogy/moderation.jinja +#: club/forms.py pedagogy/templates/pedagogy/moderation.jinja msgid "Action" msgstr "Action" @@ -220,7 +218,7 @@ msgid "You can not make loops in clubs" msgstr "Vous ne pouvez pas faire de boucles dans les clubs" #: club/models.py core/models.py counter/models.py eboutic/models.py -#: election/models.py launderette/models.py sas/models.py trombi/models.py +#: election/models.py sas/models.py trombi/models.py msgid "user" msgstr "utilisateur" @@ -228,7 +226,7 @@ msgstr "utilisateur" msgid "club" msgstr "club" -#: club/models.py counter/models.py election/models.py launderette/models.py +#: club/models.py counter/models.py election/models.py msgid "start date" msgstr "date de début" @@ -289,7 +287,6 @@ msgstr "Liste de diffusion" #: club/templates/club/club_old_members.jinja club/templates/club/mailing.jinja #: counter/templates/counter/cash_summary_list.jinja #: counter/templates/counter/stats.jinja -#: launderette/templates/launderette/launderette_admin.jinja msgid "User" msgstr "Utilisateur" @@ -341,7 +338,6 @@ msgid "Description" msgstr "Description" #: club/templates/club/club_members.jinja core/templates/core/user_clubs.jinja -#: launderette/templates/launderette/launderette_admin.jinja #: rootplace/templates/rootplace/userban.jinja msgid "Since" msgstr "Depuis" @@ -351,8 +347,7 @@ msgid "There are no members in this club." msgstr "Il n'y a pas de membres dans ce club." #: club/templates/club/club_members.jinja core/templates/core/file_detail.jinja -#: core/views/forms.py launderette/views.py -#: trombi/templates/trombi/detail.jinja +#: core/views/forms.py trombi/templates/trombi/detail.jinja msgid "Add" msgstr "Ajouter" @@ -483,9 +478,7 @@ msgstr "Méthode de paiement" #: counter/templates/counter/fragments/create_student_card.jinja #: counter/templates/counter/last_ops.jinja #: election/templates/election/election_detail.jinja -#: forum/templates/forum/macros.jinja -#: launderette/templates/launderette/launderette_admin.jinja -#: launderette/views.py pedagogy/templates/pedagogy/guide.jinja +#: forum/templates/forum/macros.jinja pedagogy/templates/pedagogy/guide.jinja #: pedagogy/templates/pedagogy/uv_detail.jinja sas/templates/sas/album.jinja #: sas/templates/sas/moderation.jinja sas/templates/sas/picture.jinja #: trombi/templates/trombi/detail.jinja @@ -526,10 +519,6 @@ msgstr "Affiches" msgid "Counters:" msgstr "Comptoirs : " -#: club/templates/club/club_tools.jinja -msgid "Manage launderettes" -msgstr "Gestion des laveries" - #: club/templates/club/edit_club.jinja core/templates/core/edit.jinja #, python-format msgid "Edit %(name)s" @@ -663,9 +652,7 @@ msgstr "Outils" #: counter/templates/counter/cash_summary_list.jinja #: counter/templates/counter/counter_list.jinja #: election/templates/election/election_detail.jinja -#: forum/templates/forum/macros.jinja -#: launderette/templates/launderette/launderette_list.jinja -#: pedagogy/templates/pedagogy/guide.jinja +#: forum/templates/forum/macros.jinja pedagogy/templates/pedagogy/guide.jinja #: pedagogy/templates/pedagogy/uv_detail.jinja sas/templates/sas/album.jinja #: trombi/templates/trombi/detail.jinja #: trombi/templates/trombi/edit_profile.jinja @@ -1191,7 +1178,7 @@ msgid "Delete from weekmail" msgstr "Supprimer du Weekmail" #: com/templates/com/weekmail_preview.jinja -#: core/templates/core/user_account_detail.jinja launderette/views.py +#: core/templates/core/user_account_detail.jinja #: pedagogy/templates/pedagogy/uv_detail.jinja #: trombi/templates/trombi/comment_moderation.jinja #: trombi/templates/trombi/export.jinja @@ -1686,7 +1673,7 @@ msgstr "url" msgid "param" msgstr "param" -#: core/models.py launderette/models.py +#: core/models.py msgid "type" msgstr "type" @@ -1824,13 +1811,6 @@ msgstr "Eboutic" msgid "Services" msgstr "Services" -#: core/templates/core/base/navbar.jinja launderette/models.py -#: launderette/templates/launderette/launderette_book.jinja -#: launderette/templates/launderette/launderette_book_choose.jinja -#: launderette/templates/launderette/launderette_main.jinja -msgid "Launderette" -msgstr "Laverie" - #: core/templates/core/base/navbar.jinja core/templates/core/file.jinja #: core/views/files.py msgid "Files" @@ -2066,12 +2046,7 @@ msgstr "Cotisant jusqu'au %(subscription_end)s" msgid "Account number: " msgstr "Numéro de compte : " -#: core/templates/core/macros.jinja launderette/models.py -msgid "Slot" -msgstr "Créneau" - #: core/templates/core/macros.jinja -#: launderette/templates/launderette/launderette_admin.jinja msgid "Tokens" msgstr "Jetons" @@ -2908,7 +2883,7 @@ msgstr "Espèces" msgid "Credit card" msgstr "Carte bancaire" -#: counter/apps.py counter/models.py launderette/models.py +#: counter/apps.py counter/models.py msgid "counter" msgstr "comptoir" @@ -3104,7 +3079,7 @@ msgstr "Bureau" msgid "sellers" msgstr "vendeurs" -#: counter/models.py launderette/models.py +#: counter/models.py msgid "token" msgstr "jeton" @@ -3316,7 +3291,6 @@ msgid "There is no cash register summary in this website." msgstr "Il n'y a pas de relevé de caisse dans ce site web." #: counter/templates/counter/counter_click.jinja -#: launderette/templates/launderette/launderette_admin.jinja msgid "Selling" msgstr "Vente" @@ -3340,8 +3314,6 @@ msgstr "Annuler (ANN)" #: counter/templates/counter/fragments/create_refill.jinja #: counter/templates/counter/fragments/create_student_card.jinja #: counter/templates/counter/invoices_call.jinja -#: launderette/templates/launderette/launderette_admin.jinja -#: launderette/templates/launderette/launderette_click.jinja #: sas/templates/sas/picture.jinja #: subscription/templates/subscription/stats.jinja msgid "Go" @@ -3409,7 +3381,6 @@ msgid "There is no counters in this website." msgstr "Il n'y a pas de comptoirs dans ce site web." #: counter/templates/counter/counter_main.jinja -#: launderette/templates/launderette/launderette_click.jinja #, python-format msgid "%(counter_name)s counter" msgstr "Comptoir %(counter_name)s" @@ -4307,117 +4278,6 @@ msgstr "Galaxie de %(user_name)s" msgid "This citizen has not yet joined the galaxy" msgstr "Ce citoyen n'a pas encore rejoint la galaxie" -#: launderette/models.py -msgid "launderette" -msgstr "laverie" - -#: launderette/models.py -msgid "is working" -msgstr "fonctionne" - -#: launderette/models.py -msgid "Machine" -msgstr "Machine" - -#: launderette/models.py -msgid "borrow date" -msgstr "date d'emprunt" - -#: launderette/models.py -msgid "Token" -msgstr "Jeton" - -#: launderette/models.py launderette/views.py -msgid "Token name can not be blank" -msgstr "Le nom du jeton ne peut pas être vide" - -#: launderette/models.py -msgid "machine" -msgstr "machine" - -#: launderette/templates/launderette/launderette_admin.jinja -msgid "Launderette admin" -msgstr "Gestion de la laverie" - -#: launderette/templates/launderette/launderette_admin.jinja -msgid "Sell" -msgstr "Vendre" - -#: launderette/templates/launderette/launderette_admin.jinja -msgid "Machines" -msgstr "Machines" - -#: launderette/templates/launderette/launderette_admin.jinja -msgid "New machine" -msgstr "Nouvelle machine" - -#: launderette/templates/launderette/launderette_admin.jinja -#: launderette/views.py -msgid "Type" -msgstr "Type" - -#: launderette/templates/launderette/launderette_admin.jinja -msgid "Name" -msgstr "Nom" - -#: launderette/templates/launderette/launderette_book.jinja -msgid "Choose" -msgstr "Choisir" - -#: launderette/templates/launderette/launderette_book.jinja -msgid "Washing and drying" -msgstr "Lavage et séchage" - -#: launderette/templates/launderette/launderette_book.jinja sith/settings.py -msgid "Washing" -msgstr "Lavage" - -#: launderette/templates/launderette/launderette_book.jinja sith/settings.py -msgid "Drying" -msgstr "Séchage" - -#: launderette/templates/launderette/launderette_list.jinja -msgid "Launderette admin list" -msgstr "Liste des laveries" - -#: launderette/templates/launderette/launderette_list.jinja -msgid "New launderette" -msgstr "Nouvelle laverie" - -#: launderette/templates/launderette/launderette_list.jinja -msgid "There is no launderette in this website." -msgstr "Il n'y a pas de laverie dans ce site web." - -#: launderette/templates/launderette/launderette_main.jinja -msgid "Edit presentation page" -msgstr "Éditer la page de présentation" - -#: launderette/templates/launderette/launderette_main.jinja -msgid "Book launderette slot" -msgstr "Réserver un créneau de laverie" - -#: launderette/views.py -msgid "Tokens, separated by spaces" -msgstr "Jetons, séparés par des espaces" - -#: launderette/views.py -#, python-format -msgid "Token %(token_name)s does not exists" -msgstr "Le jeton %(token_name)s n'existe pas" - -#: launderette/views.py -#, python-format -msgid "Token %(token_name)s already exists" -msgstr "Un jeton %(token_name)s existe déjà" - -#: launderette/views.py -msgid "User has booked no slot" -msgstr "L'utilisateur n'a pas réservé de créneau" - -#: launderette/views.py -msgid "Token not found" -msgstr "Jeton non trouvé" - #: matmat/templates/matmat/search_form.jinja msgid "Search user" msgstr "Rechercher un utilisateur" diff --git a/mkdocs.yml b/mkdocs.yml index 992cc38e..ffa4a8b4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -86,10 +86,11 @@ nav: - antispam: - reference/antispam/models.md - reference/antispam/forms.md - - apikey: - - reference/apikey/auth.md - - reference/apikey/hashers.md - - reference/apikey/models.md + - api: + - reference/api/auth.md + - reference/api/hashers.md + - reference/api/models.md + - reference/api/perms.md - club: - reference/club/models.md - reference/club/views.md diff --git a/pedagogy/api.py b/pedagogy/api.py index b1944ce4..ae8b7ea8 100644 --- a/pedagogy/api.py +++ b/pedagogy/api.py @@ -8,8 +8,8 @@ from ninja_extra import ControllerBase, api_controller, paginate, route from ninja_extra.exceptions import NotFound from ninja_extra.pagination import PageNumberPaginationExtra, PaginatedResponseSchema -from apikey.auth import ApiKeyAuth -from core.auth.api_permissions import HasPerm +from api.auth import ApiKeyAuth +from api.permissions import HasPerm from pedagogy.models import UV from pedagogy.schemas import SimpleUvSchema, UvFilterSchema, UvSchema from pedagogy.utbm_api import UtbmApiClient diff --git a/sas/api.py b/sas/api.py index 83d7f0c8..fa37e974 100644 --- a/sas/api.py +++ b/sas/api.py @@ -13,8 +13,8 @@ from ninja_extra.permissions import IsAuthenticated from ninja_extra.schemas import PaginatedResponseSchema from pydantic import NonNegativeInt -from apikey.auth import ApiKeyAuth -from core.auth.api_permissions import ( +from api.auth import ApiKeyAuth +from api.permissions import ( CanAccessLookup, CanEdit, CanView, diff --git a/sith/settings.py b/sith/settings.py index 9e0165fe..857d8824 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -125,7 +125,7 @@ INSTALLED_APPS = ( "pedagogy", "galaxy", "antispam", - "apikey", + "api", ) MIDDLEWARE = (