import logging import time from urllib.parse import quote_plus, urlparse from django.views.generic import View, TemplateView, FormView from django.http import HttpResponseRedirect, HttpResponseBadRequest from django.conf import settings from django.utils.http import http_date from django.urls import reverse from pingcap_sso.utils.mixins import LoginRequiredMixin from pingcap_sso.utils.requests import get_safe_redirect_uri from pingcap_sso.lib.sso import ( sync_cookie_url, set_asktug_session_cookie ) from pingcap_sso.forms.sso import UpdatePhoneForm logger = logging.getLogger(__name__) def should_update_phone(request): if request.user.is_authenticated and not request.user.phone: return True return False class SyncCookieView(View): def get(self, request, *args, **kwargs): if not request.user.is_authenticated: return HttpResponseBadRequest( '出现了一些问题,您没有登录。可能的原因是:浏览器禁用了 Cookie。您可以尝试重新登录') redirect_to = get_safe_redirect_uri( request.GET.get('redirect_to'), self.request) if should_update_phone(request): request.session['redirect_to'] = redirect_to return HttpResponseRedirect(reverse('update-phone')) asktug_session_cookie = set_asktug_session_cookie( request, request.user, request.session.session_key ) max_age = settings.SESSION_COOKIE_AGE expires_time = time.time() + max_age expires = http_date(expires_time) response = HttpResponseRedirect(redirect_to) response.set_cookie( '_t', asktug_session_cookie, max_age=max_age, expires=expires, secure=True, httponly=True, ) return response class AskTUGLoginView(View): def get(self, request, *args, **kwargs): return_path = request.GET.get('return_path', '/') asktug_url_parse = urlparse(settings.SSO_SYNC_COOKIE_ASKTUG_COM_CALLBACK) redirect_to = '{}://{}{}'.format( asktug_url_parse.scheme, asktug_url_parse.netloc, return_path ) return HttpResponseRedirect( '{}{}?redirect_to={}'.format( settings.SSO_PROVIDER_ENDPOINT, reverse('login'), quote_plus( get_safe_redirect_uri(redirect_to, self.request) ), ) ) class SsoSetCookieTemplateView(LoginRequiredMixin, TemplateView): template_name = 'pingcap_sso/sso_set_cookie.html' def get_context_data(self, **kwargs): context = super(SsoSetCookieTemplateView, self).get_context_data(**kwargs) redirect_to = get_safe_redirect_uri( self.request.GET.get('redirect_to'), self.request) context['redirect_to'] = sync_cookie_url(redirect_to) context['sso_set_cookies'] = settings.SSO_SET_COOKIES return context class SsoSetCookieView(LoginRequiredMixin, View): def get(self, request, *args, **kwargs): try: sys = request.GET.get('sys') set_cookie_url = settings.SSO_SET_COOKIES[sys] return HttpResponseRedirect(set_cookie_url.format( ssid=request.session.session_key, uid=request.user.openid)) except KeyError: return HttpResponseRedirect('/') class UpdatePhoneView(LoginRequiredMixin, FormView): form_class = UpdatePhoneForm template_name = 'pingcap_sso/update_phone.html' def dispatch(self, request, *args, **kwargs): if not should_update_phone(request): return HttpResponseRedirect(reverse('index')) return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): kwargs = super().get_context_data(**kwargs) redirect_to = self.request.session.get('redirect_to', reverse('index')) kwargs['logout_url'] = f'{reverse("logout")}?redirect_to={redirect_to}' return kwargs def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs['user'] = self.request.user return kwargs def form_valid(self, form): form.save() return HttpResponseRedirect(sync_cookie_url(self.request.session.pop('redirect_to', reverse('index'))))