from django.conf import settings from django.contrib import messages from django.contrib.auth import get_user_model from django.contrib.auth import login from django.contrib.auth.decorators import login_required from django.http import HttpResponseRedirect from django.urls import reverse from django.utils import timezone from django.utils.decorators import method_decorator from django.utils.translation import gettext_lazy as _ from django.views.generic import DetailView, CreateView, UpdateView from rest_framework import generics from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements from apps.gooyal_oauth2.validators import OAuth2Validator from apps.users.forms import OAUTHLoginRequestForm # from apps.users.forms import AccountUpdateForm from apps.users.models import User, OAuthCode UserModel = get_user_model() class OAUTHLoginRequestView(CreateView): model = OAuthCode form_class = OAUTHLoginRequestForm template_name = 'users/login_request.html' def form_valid(self, form): redirect_uri = self.request.build_absolute_uri(reverse('users:login_callback')) self.object: OAuthCode = form.save(commit=False) self.object.redirect_uri = redirect_uri self.object.generate_code_verifier() self.object.save() return HttpResponseRedirect(self.object.generate_login_url()) def form_invalid(self, form): for error_key in form.errors: for error_list in form.errors[error_key].data: for error in error_list: key = _(error_key) messages.error(self.request, f"{key}: {error}") return super().form_invalid(form) class OAUTHLoginCallbackView(DetailView): model = OAuthCode template_name = 'users/login_callback.html' def get_object(self, queryset=None): state = self.request.GET.get('state') code = self.request.GET.get('code') obj = OAuthCode.objects.filter(pk=state).first() if obj: obj.code = code obj.save() return obj def introspect_token(self, token): url = settings.OAUTH2_PROVIDER['RESOURCE_SERVER_INTROSPECTION_URL'] credentials = settings.OAUTH2_PROVIDER['RESOURCE_SERVER_INTROSPECTION_CREDENTIALS'] validator = OAuth2Validator() access_token = validator._get_token_from_authentication_server(token, url, None, credentials) return access_token def get_context_data(self, **kwargs): redirect_uri = self.request.build_absolute_uri(reverse('users:login_callback')) data = self.object.validate_code(redirect_uri=redirect_uri) # {'access_token': 'WhnIAfci6yIyTsh63PPqM1HXfXqKvr', 'expires_in': 36000, 'token_type': 'Bearer', # 'scope': 'wallet.wallet:get_balance wallet.transaction:list', # 'refresh_token': 'qRHFXXc3R3EiQKUq5BcSY2b9xuTm0d'} # # from oauth2_provider.models import get_access_token_model, get_application_model access_token = self.introspect_token(data['access_token']) login(self.request, access_token.user, backend='django.contrib.auth.backends.ModelBackend') # AccessToken = get_access_token_model() # access_token = AccessToken.objects.create( # token=data['access_token'], # scope=data['scope'], # expires=timezone.now() + timedelta(data['scope']), # ) return super().get_context_data(**kwargs) @method_decorator(login_required, name='dispatch') class AccountDetailView(DetailView): model = User template_name = 'users/account_detail.html' def get_object(self, queryset=None): return self.request.user @method_decorator(login_required, name='dispatch') class AccountUpdateView(UpdateView): model = User template_name = 'users/account_update.html' # form_class = AccountUpdateForm def get_success_url(self): messages.success(self.request, 'عملیات انجام شد.') return reverse('users:account_detail') def get_object(self, queryset=None): return self.request.user