add redirects on login
This commit is contained in:
parent
bac279ae9e
commit
d35b50ad70
|
@ -131,7 +131,7 @@ class PsychTestAnswers(models.Model):
|
|||
verbose_name = "Ответ на психологический тест"
|
||||
verbose_name_plural = "Ответы на психологический тест"
|
||||
|
||||
class AuthTokens(models.Model):
|
||||
class AuthToken(models.Model):
|
||||
user = models.BigIntegerField(null=False, verbose_name='ID Пользователя, которому принадлежит токен');
|
||||
key = models.TextField(verbose_name='Ключ API');
|
||||
expires = models.BigIntegerField(verbose_name='Когда ключ истечет (Unix timestamp)');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
from .models import Apartament, User
|
||||
from .models import Apartament, User, AuthToken
|
||||
|
||||
|
||||
class ApartamentListSerializer(serializers.ModelSerializer):
|
||||
|
@ -26,4 +26,9 @@ class PsychTestAddResultSerializer(serializers.ModelSerializer):
|
|||
class PublicUserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
exclude = ('favorites_apartments', 'comparison_apartments')
|
||||
exclude = ('favorites_apartments', 'comparison_apartments')
|
||||
|
||||
class TokenSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = AuthToken
|
||||
fields = '__all__'
|
|
@ -10,13 +10,15 @@ 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 .models import Apartament, User, PsychTestAnswers, AuthToken
|
||||
from .serializer import (ApartamentListSerializer,
|
||||
ApartamentDetailSerializer,
|
||||
PsychTestAddResultSerializer,
|
||||
PublicUserSerializer)
|
||||
PublicUserSerializer,
|
||||
TokenSerializer)
|
||||
|
||||
import json, math, random, re, requests, oidc_client, base64, hashlib
|
||||
import json, math, random, re, requests, oidc_client, base64, uuid, time, ipware as iplib
|
||||
ipware = iplib.IpWare();
|
||||
|
||||
class ApartamentViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""Вывод списка квартир или отдельной квартиры"""
|
||||
|
@ -185,7 +187,7 @@ def register(oid, provider_id, name):
|
|||
# discord=,
|
||||
# city=,
|
||||
role='s',
|
||||
# photo_provider=,
|
||||
photo_provider='VVSU',
|
||||
openid_addr=oid,
|
||||
openid_id=provider_id,
|
||||
);
|
||||
|
@ -206,7 +208,45 @@ def get_oauth_data(remote, key):
|
|||
'User-Agent': 'curl/8.1'
|
||||
}).json();
|
||||
|
||||
def create_auth_token(userid, ip):
|
||||
|
||||
try:
|
||||
token = AuthToken.objects.get(user=userid, ip=ip);
|
||||
if (verify_auth_token(token.key, token.ip)):
|
||||
return token;
|
||||
except AuthToken.DoesNotExist:
|
||||
0 # ignore
|
||||
|
||||
token = AuthToken(
|
||||
user=userid,
|
||||
key=str(uuid.uuid4()),
|
||||
# 2 days
|
||||
# vvv
|
||||
expires=time.time() + 60 * 60 * 24 * 2,
|
||||
ip=ip
|
||||
);
|
||||
token.save();
|
||||
return token;
|
||||
|
||||
def verify_auth_token(key, ip):
|
||||
|
||||
try:
|
||||
token = AuthToken.objects.get(key=key);
|
||||
except AuthToken.DoesNotExist:
|
||||
return False;
|
||||
|
||||
if (token.ip != ip):
|
||||
token.delete();
|
||||
return False;
|
||||
|
||||
if (token.expires > time.time()):
|
||||
token.delete();
|
||||
return False;
|
||||
|
||||
return True;
|
||||
|
||||
class UserLogin(APIView):
|
||||
|
||||
# TODO: Remove csrf exempt when index.html is loaded through django
|
||||
@csrf_exempt
|
||||
def post(self, req: HttpRequest):
|
||||
|
@ -227,18 +267,14 @@ class UserLogin(APIView):
|
|||
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);
|
||||
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'
|
||||
});
|
||||
|
||||
if ('error' in auth_data):
|
||||
return JsonResponse(auth_data);
|
||||
|
@ -246,16 +282,13 @@ class UserLogin(APIView):
|
|||
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__'}
|
||||
|
||||
vvsu_data = get_oauth_data('https://vvsu.ru/connect', auth_data['access_token']);
|
||||
|
||||
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;
|
||||
|
@ -270,7 +303,8 @@ class UserLogin(APIView):
|
|||
|
||||
return JsonResponse({
|
||||
'user_data': PublicUserSerializer(user).data,
|
||||
'new_user': new_user
|
||||
'new_user': new_user,
|
||||
'token': TokenSerializer(create_auth_token(user.id, ipware.get_client_ip(req.META)[0].exploded)).data
|
||||
});
|
||||
|
||||
class UserGet(APIView):
|
||||
|
|
|
@ -4,4 +4,4 @@ djangorestframework
|
|||
django-cors-headers
|
||||
Pillow
|
||||
requests
|
||||
oidc-client
|
||||
python-ipware
|
|
@ -14,7 +14,70 @@ class UserLoginResponse {
|
|||
id;
|
||||
}
|
||||
|
||||
class User {
|
||||
class IAPIObject {
|
||||
/**
|
||||
* Local storage key used to save data.
|
||||
* @type {string}
|
||||
*/
|
||||
static storage_key = undefined;
|
||||
|
||||
/** @returns {ThisType} */
|
||||
static restoreFromLocalStorage() {
|
||||
if (storage_key !== undefined) {
|
||||
throw Error('This doesn\'t support local storage');
|
||||
}
|
||||
if (!window.localStorage.getItem(storage_key))
|
||||
return false;
|
||||
return new APIToken(window.localStorage.getItem(storage_key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save this object to local storage
|
||||
* @throws {QuotaExceededError}
|
||||
* @returns {void}
|
||||
*/
|
||||
saveToLocalStorage() {
|
||||
|
||||
// static this
|
||||
sthis = Object.getPrototypeOf(this);
|
||||
|
||||
if (sthis.storage_key !== undefined) {
|
||||
throw Error('This doesn\'t support local storage');
|
||||
}
|
||||
window.localStorage.setItem(sthis.storage_key, this);
|
||||
}
|
||||
}
|
||||
|
||||
class APIToken extends IAPIObject {
|
||||
|
||||
static storage_key = 'pairent_api_key';
|
||||
|
||||
constructor(data) {
|
||||
this.user = data.user;
|
||||
this.key = data.key;
|
||||
this.expires = data.expires;
|
||||
this.ip = data.ip;
|
||||
}
|
||||
|
||||
/** @type {number} */
|
||||
user;
|
||||
|
||||
/** @type {string} */
|
||||
key;
|
||||
|
||||
/** A Unix timestamp (when the token will expire)
|
||||
* @type {number}
|
||||
*/
|
||||
expires;
|
||||
|
||||
/** @type {string} */
|
||||
ip;
|
||||
}
|
||||
|
||||
class User extends IAPIObject {
|
||||
|
||||
static storage_key = 'pairent_user_data';
|
||||
|
||||
constructor(data) {
|
||||
for (const key in data) {
|
||||
this[key] = data[key];
|
||||
|
@ -44,7 +107,11 @@ class User {
|
|||
}
|
||||
|
||||
const data = await axios.post(api_path('/api/auth/user/login'), response);
|
||||
return new User(data.data);
|
||||
|
||||
window.localStorage.setItem(APIToken.storage_key, data.data.token);
|
||||
window.localStorage.setItem(User.storage_key, data.data.user_data);
|
||||
|
||||
return data.data;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import { HashLoader } from "react-spinners";
|
|||
import { SigninResponse, UserManager } from 'oidc-client-ts';
|
||||
import { User } from "../../API/User";
|
||||
import FloatingBox from "../../components/UI/FloatingBox";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import constants from "../../constants";
|
||||
|
||||
|
@ -48,7 +49,13 @@ export default class LoggedIn extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
console.log(await User.login({...this.response, code_verifier}));
|
||||
const response = await User.login({...this.response, code_verifier});
|
||||
if (response.new_user) {
|
||||
// TODO: Make the page
|
||||
useNavigate('/register');
|
||||
} else {
|
||||
useNavigate('/');
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
Loading…
Reference in New Issue