from rest_framework import viewsets from rest_framework.response import Response from rest_framework.views import APIView, View from rest_framework.request import Request from django.views.decorators.csrf import csrf_exempt from django.http import HttpResponseBadRequest, HttpResponse, JsonResponse, HttpRequest from django.db.models.query import QuerySet from django.core.validators import validate_email from django.core.exceptions import ValidationError from .models import Apartament, User, PsychTestAnswers from .serializer import (ApartamentListSerializer, ApartamentDetailSerializer, PsychTestAddResultSerializer, PublicUserSerializer) import json, math, random, re, requests, oidc_client, base64, hashlib class ApartamentViewSet(viewsets.ReadOnlyModelViewSet): """Вывод списка квартир или отдельной квартиры""" def get_queryset(self): apartaments = Apartament.objects.all() return apartaments def get_serializer_class(self): if self.action == 'list': return ApartamentListSerializer elif self.action == "retrieve": return ApartamentDetailSerializer class ApartamentGetManyViewSet(viewsets.ReadOnlyModelViewSet): """Вывод отдельных квартир для сравнения""" def get_queryset(self): # получение id квартир для избранного или сравнения pk = self.request.query_params.get("pk", None) # получение id пользователя if self.action == "retrieve": # если для страницы сравнения apartaments_id = User.objects.get(pk=pk).apartaments_for_comparison.split(',') # получение id квартир elif self.action == "list": # если для страницы избранного apartaments_id = User.objects.get(pk=pk).favorites_apartaments.split(',') # получение id квартир queryset = [] for i in apartaments_id: queryset.append(Apartament.objects.get(pk=i)) return queryset def retrieve(self, request, *args, **kwargs): queryset = self.get_queryset() apartaments = [] for i in queryset: apartaments.append(ApartamentDetailSerializer(i).data) return Response({'results': apartaments}) def list(self, request, *args, **kwargs): queryset = self.get_queryset() apartaments = [] for i in queryset: apartaments.append(ApartamentListSerializer(i).data) return Response({'results': apartaments}) class ApartmentFilter(viewsets.ViewSet): """Вывод списка квартир или отдельной квартиры""" def list(self, req: Request): filters = dict(req.data); unfiltered = Apartament.objects.all(); filtered = []; # TODO: Some better converting practice? filters['price_range']['from'] = int(filters['price_range']['from']); filters['price_range']['to'] = int(filters['price_range']['to']); filters['area_range']['from'] = int(filters['area_range']['from']); filters['area_range']['to'] = int(filters['area_range']['to']); filters['rooms'] = int(filters['rooms']) for entry in unfiltered: if (filters['price_range']['from'] >= entry.price and (filters['price_range']['to'] != -1 and filters['price_range']['to'] <= entry.price)): continue; if (filters['area_range']['from'] >= entry.perimetrs and (filters['area_range']['to'] != -1 and filters['area_range']['to'] <= entry.perimetrs)): continue; if (filters['rooms'] != -1 and entry.rooms != filters['rooms']): continue; filtered.append(entry); return Response(ApartamentListSerializer(filtered, many=True).data); class PsychTestAddResultViewSet(viewsets.ViewSet): def get_object(self, pk): return User.objects.get(pk=pk) def create(self, request, pk): user = self.get_object(pk) results = request.data PsychTestAnswers.objects.create( user=user, first_question=results[0], second_question=results[1], third_question=results[2], fourth_question=results[3], fifth_question=results[4], sixth_question=results[5], seventh_question=results[6], eighth_question=results[7], nineth_question=results[8], tenth_question=results[9], eleventh_question=results[10], twelfth_question=results[11] ) return Response({'successfully': 'results post'}) class CompatibleUsersView(viewsets.ViewSet): def list(self, req: Request): user_data = dict(req.data); # TODO: Verify auth vvsu_login = user_data['openid']; # Exclude already viewed users exclude = []; if ('exclude' in user_data.keys()): exclude = user_data['exclude']; try: validate_email(vvsu_login); except ValidationError: return Request({'error': 'bad login'}, 400); try: this_user = User.objects.get(openid_addr=vvsu_login); except User.DoesNotExist: return Response({'error': 'user not found'}, 404); score = this_user.psych_test_result; users_query = User.objects.all(); users = []; for user in users_query: if (abs(user.psych_test_result - score) < 20): users.append(PublicUserSerializer(user).data); random.shuffle(users); users = users[:7]; for i in range(3): users.append(PublicUserSerializer(random.choice(users_query)).data); random.shuffle(users); return Response(users); def VVSUAuthProxy(req: Request): proxy = 'https://vvsu.ru/connect' + req.path[len('/api/auth/vvsu'):]; preq = requests.request(req.method, proxy, headers={ 'User-Agent': 'OIDC Client / Pairent', 'Origin': 'http://pairent.vvsu.ru', 'Referer': 'http://pairent.vvsu.ru' }); resp = HttpResponse(preq.content); resp.headers['Content-Type'] = preq.headers['Content-Type']; return resp; def register(oid, provider_id, name): user = User( favorites_apartments='', comparison_apartments='', name=name, # date_of_birth=, about_me='', gender='?', phone='+00000', # email=, # telegram=, # discord=, # city=, role='s', # photo_provider=, openid_addr=oid, openid_id=provider_id, ); user.save(); return user; def get_oauth_token(remote, data): return requests.post(remote + '/oauth2/token', data, headers={ 'Origin': 'https://pairent.vvsu.ru', 'Referer': 'https://pairent.vvsu.ru' }).json(); def get_oauth_data(remote, key): return requests.get(remote + '/userinfo', headers={ 'Origin': 'https://pairent.vvsu.ru', 'Authorization': 'Bearer ' + key, 'User-Agent': 'curl/8.1' }).json(); class UserLogin(APIView): # TODO: Remove csrf exempt when index.html is loaded through django @csrf_exempt def post(self, req: HttpRequest): if (req.session.has_key('auth_data')): # TODO: Return user object instead of error return JsonResponse({'error': 'already authenticated'}) if (req.content_type != 'application/json'): res = HttpResponse({'error': 'bad content type'}); res.status_code = 400; return res; data = json.loads(req.body.decode('utf8')); if not ('code' in data and 'code_verifier' in data): res = JsonResponse({'error': 'no code'}); res.status_code = 400; return res; # auth_data = get_oauth_token('https://vvsu.ru/connect', { # 'grant_type': 'authorization_code', # 'redirect_uri': 'https://pairent.vvsu.ru/sign-in/', # 'code': data['code'], # 'code_verifier': data['code_verifier'], # 'client_id': 'it-hub-client', # 'client_secret': 'U8y@uPVee6Q^*729esHTo4Vd' # }); auth_data = {'access_token': 'gcH96CSYQBeiq9te1lpJV4T9mBH4UabT4_m6fJQFQK4.K4GA7sXFtBEM26kDladZjZ8phsI3aRPmqu5oRts4Csg', 'expires_in': 3600, 'id_token': 'eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzpoeWRyYS5vcGVuaWQuaWQtdG9rZW4iLCJ0eXAiOiJKV1QifQ.eyJhY3IiOiIwIiwiYXRfaGFzaCI6ImJIZS1pWmlvX2Npa3diOFc3bnBkbEEiLCJhdWQiOlsiaXQtaHViLWNsaWVudCJdLCJhdXRoX3RpbWUiOjE2ODQyNDM0NjUsImNhbGxiYWNrX3VybCI6IiIsImV4cCI6MTY4NDI0NzA3MywiZmFtaWx5X25hbWUiOiLQn9GD0YHRgtC-0LLQsNC70L7QsiIsImdpdmVuX25hbWUiOiLQndC40LrQuNGC0LAiLCJpYXQiOjE2ODQyNDM0NzMsImlkIjoiMDk2Qzc4Q0QtNDk0My00RDU3LUJDNkQtNUNERTEyRjY4NkUzIiwiaXNzIjoiaHR0cHM6Ly93d3cudnZzdS5ydS9jb25uZWN0LyIsImp0aSI6IjU5M2FiYTQzLTU4OTQtNGZmNy1iMmU1LTdmOWZkYTZjZjFhZSIsImxvZ2luIjoiaHR0cHM6Ly9vcGVuaWQudnZzdS5ydS9ibGVrX18iLCJvcGVuaWQiOiJodHRwczovL29wZW5pZC52dnN1LnJ1L2JsZWtfXyIsInBpY3R1cmUiOiJodHRwczovL3d3dy52dnN1LnJ1L29pc2twL3Bob3RvL3B0aC5hc3A_SUQ9MDk2Qzc4Q0QtNDk0My00RDU3LUJDNkQtNUNERTEyRjY4NkUzXHUwMDI2IiwicHJvZmlsZV91cmwiOm51bGwsInJhdCI6MTY4NDI0MzQ1NCwic2lkIjoiMzEwZjU5MWEtZmNjYy00NzY3LTkzMmItYjM3OTQyZmFmMTA1Iiwic3ViIjoiaHR0cHM6Ly9vcGVuaWQudnZzdS5ydS9ibGVrX18iLCJzdXJuYW1lIjoi0J_Rg9GB0YLQvtCy0LDQu9C-0LIiLCJ0aXRsZSI6ItCh0YLRg9C00LXQvdGCIiwidnZzdV9JZEVtcGwiOm51bGwsInZ2c3VfSWRTdHVkIjoiMTk3MDgwIiwidnZzdV9JZFVzZXIiOjE5MDQ4OSwidnZzdV9sb2dpbiI6ImJsZWtfXyJ9.mClShf1lzGoKarsshafM6H2_57wrINbLSUjDQrEOAICN0V6TMNmC2zevgjxBbMl3BTIWhGJ37SNViyGvdNjPeG_S32TBr0m_vJEddZbHLzO7U7J2vqYVkiFQl8hziZkvhZUboSCu71aWexvN6rtX5grxIPAZswgGP4Mszg7ueQlhybgDELVg-UG-2OVH01-ynsfoZbaPYN6_8x44FJDUiltFbdx57kD8OEh4CdqEPTl3rL2T1U04cfNY0Ij2ivo9esEyAmuuXQCmwn_YwHO3TQc0S2Bq6DeIWa4gauynxGjPl2tf4fcyz-XOVWGeMNIwXCHvIDB_aHsZromG3UV2gY3ji-RlkEq81mYzFjOwB-LArkJQ68zQZlu5cFKqtWvZOzKqCzDDRUvfiRTu3OexQse_g10EeMi7vSeocGnfETlq5utar05gFGY-DxSaFYNCKzxqqS8V78d5aRFrWcQNbE6CVpKZPbZBBEQ-ItX-wh1FEyL3Uw-MsDztwJu6p_ftwRZLF0lk3ECFlbFt4NzzutFYqwS1s5ZoSZa-ylLY8PsZdr9gj58jBYD8c1foXZ9I_KzC_bYDOyUQfjec5njxGWN3828TvySclHkXMUgQxCM16OmPq8MICk_tfhqOSezcs0JpXIEtHHn0h9HNavZuhMTIaTWErYRIIxEPgtBn8r8', 'scope': 'openid vvsu_IdUser vvsu_IdEmpl vvsu_IdStud vvsu_login given_name family_name', 'token_type': 'bearer'} # print(auth_data); if ('error' in auth_data): return JsonResponse(auth_data); user = None; new_user = False; # vvsu_data = get_oauth_data('https://vvsu.ru/connect', auth_data['access_token']); vvsu_data = {'acr': '0', 'aud': ['it-hub-client'], 'auth_time': 1684243465, 'callback_url': '', 'family_name': 'Пустовалов', 'given_name': 'Никита', 'iat': 1684243466, 'id': '096C78CD-4943-4D57-BC6D-5CDE12F686E3', 'iss': 'https://www.vvsu.ru/connect/', 'login': 'https://openid.vvsu.ru/blek__', 'openid': 'https://openid.vvsu.ru/blek__', 'picture': 'https://www.vvsu.ru/oiskp/photo/pth.asp?ID=096C78CD-4943-4D57-BC6D-5CDE12F686E3&', 'profile_url': None, 'rat': 1684243454, 'sub': 'https://openid.vvsu.ru/blek__', 'surname': 'Пустовалов', 'title': 'Студент', 'vvsu_IdEmpl': None, 'vvsu_IdStud': '197080', 'vvsu_IdUser': 190489, 'vvsu_login': 'blek__'} if ('error' in vvsu_data): res = JsonResponse(vvsu_data); res.status_code = 500; return res; req.session['auth_data'] = vvsu_data; if ('error' in vvsu_data): res = JsonResponse(vvsu_data); res.status_code = 500; return res vvsu_data['vvsu_login'] += '@vvsu.ru'; try: user = User.objects.get(openid_addr=vvsu_data['vvsu_login']); except User.DoesNotExist: user = register(vvsu_data['vvsu_login'], vvsu_data['id'], f"{vvsu_data['given_name']} {vvsu_data['family_name']}"); new_user = True; return JsonResponse({ 'user_data': PublicUserSerializer(user).data, 'new_user': new_user }); class UserGet(APIView): def get(self, req: HttpRequest): if not ('id' in req.GET.keys() or 'login' in req.GET.keys()): res = JsonResponse({'error': 'no id or login'}); res.status_code = 400; return res; id_type = 'id' if 'id' in req.GET.keys() else 'login'; id = req.GET.get(id_type); if (id_type == 'login'): if not id.endswith('@vvsu.ru'): id += '@vvsu.ru'; id_type = 'openid_addr'; user = None; try: user = User.objects.get(**{id_type: id}); except User.DoesNotExist: res = JsonResponse({'error': 'not found'}); res.status_code = 404; return res; return JsonResponse(PublicUserSerializer(user).data);