doc: third-party auth

This commit is contained in:
imperosol
2025-10-30 17:22:00 +01:00
parent 19fc4479c2
commit ceb9f50ef3
13 changed files with 392 additions and 30 deletions

View File

@@ -23,7 +23,7 @@ class ThirdPartyAuthForm(forms.Form):
)
client_id = forms.IntegerField(widget=HiddenInput())
third_party_app = forms.CharField(widget=HiddenInput())
cgu_link = forms.URLField(widget=HiddenInput())
privacy_link = forms.URLField(widget=HiddenInput())
username = forms.CharField(widget=HiddenInput())
callback_url = forms.URLField(widget=HiddenInput())
signature = forms.CharField(widget=HiddenInput())

View File

@@ -66,7 +66,11 @@ class ApiClient(models.Model):
return all(self.has_perm(perm) for perm in perm_list)
def reset_hmac(self, *, commit: bool = True) -> str:
"""Reset and return the HMAC key for this client."""
"""Reset and return the HMAC key for this client.
Args:
commit: if True (the default), persist the new hmac in db.
"""
self.hmac_key = get_hmac_key()
if commit:
self.save()

View File

@@ -1,5 +1,5 @@
from ninja import ModelSchema
from pydantic import Field
from ninja import ModelSchema, Schema
from pydantic import Field, HttpUrl
from api.models import ApiClient
from core.schemas import SimpleUserSchema
@@ -12,3 +12,12 @@ class ApiClientSchema(ModelSchema):
owner: SimpleUserSchema
permissions: list[str] = Field(alias="all_permissions")
class ThirdPartyAuthParamsSchema(Schema):
client_id: int
third_party_app: str
privacy_link: HttpUrl
username: str
callback_url: HttpUrl
signature: str

View File

@@ -14,8 +14,8 @@
{% endtrans %}
</p>
<p class="margin-bottom">
{% trans trimmed app=third_party_app, cgu_link=third_party_cgu, sith_cgu_link=sith_cgu %}
The privacy policies of <a href="{{ cgu_link }}">{{ app }}</a>
{% trans trimmed app=third_party_app, privacy_link=third_party_cgu, sith_cgu_link=sith_cgu %}
The privacy policies of <a href="{{ privacy_link }}">{{ app }}</a>
and of <a href="{{ sith_cgu_link }}">the Students' Association</a>
applies as soon as the form is submitted.
{% endtrans %}

View File

@@ -9,6 +9,7 @@ from pytest_django.asserts import assertRedirects
from api.models import ApiClient, get_hmac_key
from core.baker_recipes import subscriber_user
from core.schemas import UserProfileSchema
from core.utils import hmac_hexdigest
@@ -34,14 +35,14 @@ class TestThirdPartyAuth(TestCase):
self.query = {
"client_id": self.api_client.id,
"third_party_app": "app",
"cgu_link": "https://foobar.fr/",
"privacy_link": "https://foobar.fr/",
"username": "bibou",
"callback_url": "https://callback.fr/",
}
self.query["signature"] = hmac_hexdigest(self.api_client.hmac_key, self.query)
self.callback_data = {"user_id": self.user.id}
self.callback_data = {"user": UserProfileSchema.from_orm(self.user).model_dump()}
self.callback_data["signature"] = hmac_hexdigest(
self.api_client.hmac_key, self.callback_data
self.api_client.hmac_key, self.callback_data["user"]
)
def test_auth_ok(self):

View File

@@ -10,26 +10,16 @@ from django.core.exceptions import PermissionDenied
from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import FormView, TemplateView
from ninja import Schema
from ninja_extra.shortcuts import get_object_or_none
from pydantic import HttpUrl
from api.forms import ThirdPartyAuthForm
from api.models import ApiClient
from api.schemas import ThirdPartyAuthParamsSchema
from core.models import SithFile
from core.schemas import UserProfileSchema
from core.utils import hmac_hexdigest
class ThirdPartyAuthParamsSchema(Schema):
client_id: int
third_party_app: str
cgu_link: HttpUrl
username: str
callback_url: HttpUrl
signature: str
class ThirdPartyAuthView(LoginRequiredMixin, FormView):
form_class = ThirdPartyAuthForm
template_name = "api/third_party/auth.jinja"
@@ -93,7 +83,7 @@ class ThirdPartyAuthView(LoginRequiredMixin, FormView):
def get_context_data(self, **kwargs):
return super().get_context_data(**kwargs) | {
"third_party_app": self.params.third_party_app,
"third_party_cgu": self.params.cgu_link,
"third_party_cgu": self.params.privacy_link,
"sith_cgu": SithFile.objects.get(id=settings.SITH_CGU_FILE_ID),
}