1import logging
2
3from plain.auth.views import AuthViewMixin
4from plain.http import ResponseBadRequest, ResponseRedirect
5from plain.templates import Template
6from plain.views import View
7
8from .exceptions import (
9 OAuthError,
10 OAuthStateMismatchError,
11 OAuthUserAlreadyExistsError,
12)
13from .providers import get_oauth_provider_instance
14
15logger = logging.getLogger(__name__)
16
17
18class OAuthLoginView(View):
19 def post(self):
20 request = self.request
21 provider = self.url_kwargs["provider"]
22 if request.user:
23 return ResponseRedirect("/")
24
25 provider_instance = get_oauth_provider_instance(provider_key=provider)
26 return provider_instance.handle_login_request(request=request)
27
28
29class OAuthCallbackView(View):
30 """
31 The callback view is used for signup, login, and connect.
32 """
33
34 def get(self):
35 request = self.request
36 provider = self.url_kwargs["provider"]
37 provider_instance = get_oauth_provider_instance(provider_key=provider)
38 try:
39 return provider_instance.handle_callback_request(request=request)
40 except OAuthUserAlreadyExistsError:
41 template = Template("oauth/error.html")
42 return ResponseBadRequest(
43 template.render(
44 {
45 "oauth_error": "A user already exists with this email address. Please log in first and then connect this OAuth provider to the existing account."
46 }
47 )
48 )
49 except OAuthStateMismatchError:
50 template = Template("oauth/error.html")
51 return ResponseBadRequest(
52 template.render(
53 {
54 "oauth_error": "The state parameter did not match. Please try again."
55 }
56 )
57 )
58 except OAuthError as e:
59 logger.exception("OAuth error")
60 template = Template("oauth/error.html")
61 return ResponseBadRequest(template.render({"oauth_error": str(e)}))
62
63
64class OAuthConnectView(AuthViewMixin, View):
65 def post(self):
66 request = self.request
67 provider = self.url_kwargs["provider"]
68 provider_instance = get_oauth_provider_instance(provider_key=provider)
69 return provider_instance.handle_connect_request(request=request)
70
71
72class OAuthDisconnectView(AuthViewMixin, View):
73 def post(self):
74 request = self.request
75 provider = self.url_kwargs["provider"]
76 provider_instance = get_oauth_provider_instance(provider_key=provider)
77 # try:
78 return provider_instance.handle_disconnect_request(request=request)
79 # except OAuthCannotDisconnectError:
80 # return render(
81 # request,
82 # "oauth/error.html",
83 # {
84 # "oauth_error": "This connection can't be removed. You must have a usable password or at least one active connection."
85 # },
86 # status_code=400,
87 # )