Plain is headed towards 1.0! Subscribe for development updates →

 1from __future__ import annotations
 2
 3from typing import TYPE_CHECKING, Any
 4
 5from plain import forms
 6from plain.auth import get_user_model
 7from plain.email import TemplateEmail
 8
 9from .links import generate_link_url
10
11if TYPE_CHECKING:
12    from plain.http import Request
13
14
15class LoginLinkForm(forms.Form):
16    email = forms.EmailField()
17    next = forms.CharField(required=False)
18
19    def maybe_send_link(
20        self, request: Request, expires_in: int = 60 * 60
21    ) -> int | None:
22        user_model = get_user_model()
23        email = self.cleaned_data["email"]
24        try:
25            user = user_model.query.get(email__iexact=email)
26        except user_model.DoesNotExist:
27            user = None
28
29        if user:
30            url = generate_link_url(
31                request=request, user=user, email=email, expires_in=expires_in
32            )
33
34            if next_url := self.cleaned_data.get("next"):
35                url += f"?next={next_url}"
36
37            email = self.get_template_email(
38                email=email,
39                context={"user": user, "url": url, "expires_in": expires_in},
40            )
41            return email.send()
42
43        return None
44
45    def get_template_email(
46        self, *, email: str, context: dict[str, Any]
47    ) -> TemplateEmail:
48        return TemplateEmail(
49            template="loginlink",
50            to=[email],
51            context=context,
52        )