add vvsu auth (still needs work)

This commit is contained in:
b1ek 2023-05-15 21:01:57 +10:00
parent 1702a2f0d8
commit 35d7148c95
Signed by: blek
GPG Key ID: 14546221E3595D0C
8 changed files with 210 additions and 7 deletions

View File

@ -1,4 +1,5 @@
from django.urls import path
from django.urls import path, re_path
# from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from . import views
@ -10,5 +11,6 @@ urlpatterns = format_suffix_patterns([
path("apartaments/favorite/", views.ApartamentGetManyViewSet.as_view({'get': 'list'})), # пример: apartaments/favorite/?user_id=1 user_id - id пользователя
path("apartaments/filters/", views.ApartmentFilter.as_view({'post': 'list'})),
path("psych_test/add_result/<int:pk>", views.PsychTestAddResultViewSet.as_view({'patch': 'update'})), # пример: psych_test/add_result/1/?result=50 result - результат псих теста пользователя
path("users/get_compatible", views.CompatibleUsersView.as_view({'post': 'list'}))
path("users/get_compatible", views.CompatibleUsersView.as_view({'post': 'list'})),
re_path(r'^auth/vvsu/', views.VVSUAuthProxy),
])

View File

@ -3,7 +3,7 @@ from rest_framework.response import Response
from rest_framework.views import APIView, View
from rest_framework.request import Request
from django.http import HttpResponseBadRequest
from django.http import HttpResponseBadRequest, HttpResponse
from django.db.models.query import QuerySet
from django.core.validators import validate_email
@ -15,7 +15,7 @@ from .serializer import (ApartamentListSerializer,
PsychTestAddResultSerializer,
PublicUserSerializer)
import json, math, random, re
import json, math, random, re, requests
class ApartamentViewSet(viewsets.ReadOnlyModelViewSet):
"""Вывод списка квартир или отдельной квартиры"""
@ -137,4 +137,18 @@ class CompatibleUsersView(viewsets.ViewSet):
random.shuffle(users);
return Response(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;

View File

@ -2,4 +2,5 @@ mysqlclient
django
djangorestframework
django-cors-headers
Pillow
Pillow
requests

View File

@ -0,0 +1,34 @@
import { styled } from "styled-components";
const BlueButton = styled.button`
background: white;
border: 2px solid royalblue;
border-radius: 12px;
color: royalblue;
font-weight: 600;
line-height: 20px;
transition: 150ms ease;
width: 100%;
font-size: 10.5pt;
height: 36px;
padding: 6px 10px;
clip-path: border-box;
box-sizing: border-box;
& svg {
fill: royalblue;
margin: 0;
margin-right: 6px;
transform: translateY(2px);
}
&:hover {
color: white;
background: royalblue;
}
&:hover svg {
fill: white
}
`;
export default BlueButton;

View File

@ -0,0 +1 @@
// TODO: Make a logged in handler

View File

@ -0,0 +1,130 @@
import React from 'react';
import { styled } from 'styled-components';
import BlueButton from '../../components/UI/BlueButton';
import { HashLoader } from 'react-spinners';
import * as OpenID from 'oidc-client-ts';
import constants from '../../constants';
const { API_ROOT } = constants;
const LoginBox = styled.div`
position: fixed;
top: 45%;
left: 50%;
transform: translate(-50%, -50%);
border: 1px solid #c2c4c2;
border-radius: 12px;
padding: 24px 36px;
background: white;
box-shadow: 0 2px 1px #00000010;
text-align: center;
& h2 {
margin: 0px 0;
}
& hr {
margin: 16px 0;
margin-bottom: 24px;
height: 0px;
border: 0;
border-bottom: 1px solid #c2c4c2;
box-shadow: 0 2px 1px #c2c4c280;
}
& p {
font-size: 8pt;
color: gray;
margin-top: 16px;
}
`;
const LoginButton = styled(BlueButton)`
font-size: 11pt;
width: 250px;
height: 60px;
padding: 16px 20px;
font-size: 11.5pt;
font-weight: 700;
cursor: ${props => props.disabled ? 'default' : 'pointer'};
& svg {
height: 12pt;
margin-left: 6px
}
&:hover {
background: ${props => props.disabled ? 'white' : 'royalblue'};
}
`;
const OIDCConfig = {
onSignIn: () => {},
authority: API_ROOT + '/api/auth/vvsu/',
client_id: 'it-hub-client',
redirect_uri: 'https://pairent.vvsu.ru/sign-in/',
scope: [
'openid',
// 'vvsu_IdUser',
// 'vvsu_IdEmpl',
// 'vvsu_IdStud',
// 'vvsu_login',
// 'given_name',
// 'family_name'
]
};
const VVSULogoSVG = () => {
return <svg xmlns="http://www.w3.org/2000/svg" xmlSpace="preserve" viewBox="0 0 451.5 155.9"><path fillRule="evenodd" d="M408.7 0h42.8L416 102.5l-2.8 8.1c-8.2 23.9-33.9 43.6-58 45.2h-.6c-.8.1-1.6.1-2.5.1H348c-.8 0-1.6 0-2.4-.1h-43l15.7-45.2.3-.8h35.7c9.1 0 19.2-7.8 22.5-17.2l.4-1 1.2-3.5h-32.7c-4.4 0-19.5 0-13.1-18.5l4.4-12.9 3.9-11.2L356.5 0H393l-21.7 62.8H387c2.6-7.5 15.8-45.6 21.7-62.8zm-91.2 0h25.9l-15.7 45.3h-7c-9.6 0-20.1 7.9-23.5 17.4L265 155.9c-.5 0-1-.1-1.5-.1h-43l15.8-45.2 7.8-22.6 14.8-42.5c8.3-24.1 34.4-44 58.6-45.2V0zM208 0h48.7l-20.1 58.1c-3.2 9.1-9.4 15.2-19.4 17.2l16.8.1-12.3 35.2c-8.2 23.9-33.9 43.6-58 45.2h-.7c-.8.1-1.6.1-2.5.1h-4.1c-.8 0-1.6 0-2.4-.1h-43l38.2-110.4c8.4-24.1 34.4-44 58.7-45.2l.1-.2zm-12.7 40.8h15.4l-8.1 23h-23.9l4.4-12.5c1.7-4.6 7.3-10.5 12.2-10.5zm-25.6 48.8H194l-5.5 16.1c-1.1 3.4-6.1 10.8-13.6 10.8h-14.1l8.9-26.9zM96.9 0h48.7l-20.2 58.1c-3.2 9.1-9.4 15.2-19.4 17.2l16.8.1-9.3 27.1h-.2l-2.8 8.1c-8.2 23.9-33.9 43.6-58 45.2h-.6c-.8.1-1.7.1-2.5.1h-4.1c-.8 0-1.6 0-2.4-.1H0l15.7-45.2L23.6 88l14.7-42.5C46.7 21.4 72.7 1.5 97 .3V0zM84.2 40.8h15.4l-8.1 23H67.6L72 51.3c1.7-4.6 7.3-10.5 12.2-10.5zM58.6 89.6h24.3l-5.5 16.1c-1.1 3.4-6.1 10.8-13.5 10.8H49.7l8.9-26.9z" clipRule="evenodd"/></svg>;
}
export default class LoginPage extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false
}
this.openid = this.openid.bind(this);
}
async openid() {
if (this.state.loading === true) return;
this.setState({loading: true});
OpenID.Log.setLogger(console);
OpenID.Log.setLevel(OpenID.Log.DEBUG);
let client = new OpenID.OidcClient(OIDCConfig);
const req = await client.createSigninRequest({});
window.location.href = req.url;
}
render() {
return (
<div style={{height: '50vh'}}>
<LoginBox>
<h2>Вход</h2>
<hr/>
<LoginButton onClick={this.openid} disabled={this.state.loading}>
{
this.state.loading ?
<HashLoader size='24px' color='#4169e1' /> :
<>
Войти через
<VVSULogoSVG />
</>
}
</LoginButton>
<p>
Вход осуществляется только через<br/>
Систему Единого Входа ВВГУ
</p>
</LoginBox>
</div>
);
}
}

View File

@ -3,6 +3,7 @@ import Comparisons from "../pages/Comparisons";
import IndexApartment from "../pages/IndexApartment";
import IndexPage from "../pages/IndexPage";
import Tinder from "../pages/Tinder";
import LoginPage from "../pages/LoginPage";
// НА ПРОДАШКЕНЕ СДЕЛАТЬ ПРИВАТНЫЕ МАРШРУТЫ
// export const privateRoutes = [
@ -16,7 +17,9 @@ export default Object.freeze({
{ path: '/apartment/:id', component: <IndexApartment />, exact: true },
{ path: '/favorites', component: <Favorites />, exact: true },
{ path: '/comparisons', component: <Comparisons />, exact: true },
{ path: '/tinder', component: <Tinder />, exact: true }
{ path: '/tinder', component: <Tinder />, exact: true },
{ path: '/login', component: <LoginPage />, exact: true },
{ path: '/sign-in', component: <LoginPage />, exact: true }
],
privateRoutes: []
})

View File

@ -1821,6 +1821,11 @@ cross-spawn@^7.0.2:
shebang-command "^2.0.0"
which "^2.0.1"
crypto-js@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf"
integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==
css-color-keywords@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
@ -2802,6 +2807,11 @@ json5@^2.2.2:
array-includes "^3.1.5"
object.assign "^4.1.3"
jwt-decode@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59"
integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==
levn@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
@ -2989,6 +2999,14 @@ object.values@^1.1.6:
define-properties "^1.1.4"
es-abstract "^1.20.4"
oidc-client-ts@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/oidc-client-ts/-/oidc-client-ts-2.2.3.tgz#85c6382540cf59383896d6470c9c3908d5d625f7"
integrity sha512-nheMI8kSJu8L+Pmg7E4ra+LJ7lOTK60IfyblFmyx5qaJwwDpc1zkzFyH9eyERAQ92xUTF1uaB8WiaVxXATjLGA==
dependencies:
crypto-js "^4.1.1"
jwt-decode "^3.1.2"
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"