rename apikey to api

This commit is contained in:
imperosol 2025-06-04 09:49:11 +02:00
parent b727b78995
commit 590831c7b8
31 changed files with 172 additions and 284 deletions

View File

@ -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)

View File

@ -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"

View File

@ -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):

View File

@ -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",
),
),

View File

@ -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))

0
api/tests/__init__.py Normal file
View File

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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(

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -1,4 +1,4 @@
::: apikey.auth
::: api.auth
handler: python
options:
heading_level: 3

View File

@ -1,4 +1,4 @@
::: apikey.hashers
::: api.hashers
handler: python
options:
heading_level: 3

View File

@ -1,4 +1,4 @@
::: apikey.auth
::: api.auth
handler: python
options:
heading_level: 3

View File

@ -0,0 +1,4 @@
::: api.permissions
handler: python
options:
heading_level: 3

View File

@ -20,13 +20,6 @@
- CanCreateMixin
- CanEditMixin
- CanViewMixin
- CanEditPropMixin
- FormerSubscriberMixin
- PermissionOrAuthorRequiredMixin
## API Permissions
::: core.auth.api_permissions
handler: python
options:
heading_level: 3

View File

@ -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

View File

@ -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).

View File

@ -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
```
</div>
@ -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 <nom de la commande>`
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

View File

@ -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

View File

@ -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 <thomas.girod@utbm.fr\n"
"Language-Team: AE info <ae.info@utbm.fr>\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"

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -125,7 +125,7 @@ INSTALLED_APPS = (
"pedagogy",
"galaxy",
"antispam",
"apikey",
"api",
)
MIDDLEWARE = (