From 601b13feb64544051aedcac1fc8a753ffa64f31c Mon Sep 17 00:00:00 2001 From: b1ek Date: Wed, 17 May 2023 02:10:17 +1000 Subject: [PATCH] finish off login --- pairent_backend/pairent_app/views.py | 3 ++ pairent_frontend_react/src/API/User.js | 49 ++++++++++++++----- .../src/pages/LoggedIn/index.jsx | 17 +++++-- .../src/pages/LoginPage/index.jsx | 22 +++++++-- 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/pairent_backend/pairent_app/views.py b/pairent_backend/pairent_app/views.py index 6bd3249..87f0ac2 100644 --- a/pairent_backend/pairent_app/views.py +++ b/pairent_backend/pairent_app/views.py @@ -251,6 +251,9 @@ class UserLogin(APIView): @csrf_exempt def post(self, req: HttpRequest): + # for debug purposes + # return HttpResponse("""{"user_data": {"id": 1, "name": "\u041d\u0438\u043a\u0438\u0442\u0430 \u041f\u0443\u0441\u0442\u043e\u0432\u0430\u043b\u043e\u0432", "date_of_birth": null, "about_me": "", "gender": "?", "phone": "+00000", "email": null, "telegram": null, "discord": null, "city": null, "role": "s", "photo_provider": "VVSU", "openid_addr": "blek__@vvsu.ru", "openid_id": "096C78CD-4943-4D57-BC6D-5CDE12F686E3"}, "new_user": false, "token": {"id": 2, "user": 1, "key": "e1c24581-523a-4f60-973f-02ba873b3edc", "expires": 1684423572, "ip": "127.0.0.1"}}"""); + if (req.session.has_key('auth_data')): # TODO: Return user object instead of error return JsonResponse({'error': 'already authenticated'}) diff --git a/pairent_frontend_react/src/API/User.js b/pairent_frontend_react/src/API/User.js index 1bfcce7..d48ee9b 100644 --- a/pairent_frontend_react/src/API/User.js +++ b/pairent_frontend_react/src/API/User.js @@ -21,30 +21,44 @@ class IAPIObject { */ static storage_key = undefined; - /** @returns {ThisType} */ - static restoreFromLocalStorage() { - if (storage_key !== undefined) { + static _checkStorageSupport() { + if (storage_key === undefined) { throw Error('This doesn\'t support local storage'); } + } + + _getStorageKey() { + return Object.getPrototypeOf(this).constructor.storage_key; + } + + _IcheckStorageSupport() { + if (this._getStorageKey() === undefined) { + throw Error('This doesn\'t support local storage'); + } + } + + /** @returns {ThisType} */ + static restoreFromLocalStorage() { + _checkStorageSupport(); if (!window.localStorage.getItem(storage_key)) return false; return new APIToken(window.localStorage.getItem(storage_key)); } + /** @returns {boolean} */ + static isCached() { + _checkStorageSupport(); + } + /** * Save this object to local storage * @throws {QuotaExceededError} * @returns {void} */ saveToLocalStorage() { + this._IcheckStorageSupport(); - // 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); + window.localStorage.setItem(this._getStorageKey(), JSON.stringify(this)); } } @@ -53,6 +67,7 @@ class APIToken extends IAPIObject { static storage_key = 'pairent_api_key'; constructor(data) { + super(); this.user = data.user; this.key = data.key; this.expires = data.expires; @@ -76,9 +91,14 @@ class APIToken extends IAPIObject { class User extends IAPIObject { + isLoggedIn() { + return false; + } + static storage_key = 'pairent_user_data'; constructor(data) { + super(); for (const key in data) { this[key] = data[key]; } @@ -107,9 +127,14 @@ class User extends IAPIObject { } const data = await axios.post(api_path('/api/auth/user/login'), response); + if (data.status !== 200) { + return false; + } - window.localStorage.setItem(APIToken.storage_key, data.data.token); - window.localStorage.setItem(User.storage_key, data.data.user_data); + if (!data.data.error) { + new APIToken(data.data.token).saveToLocalStorage(); + new User(data.data.user_data).saveToLocalStorage(); + } return data.data; } diff --git a/pairent_frontend_react/src/pages/LoggedIn/index.jsx b/pairent_frontend_react/src/pages/LoggedIn/index.jsx index eda1db9..141161c 100644 --- a/pairent_frontend_react/src/pages/LoggedIn/index.jsx +++ b/pairent_frontend_react/src/pages/LoggedIn/index.jsx @@ -4,7 +4,6 @@ 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"; @@ -33,12 +32,12 @@ export default class LoggedIn extends React.Component { constructor(props) { super(props); this.response = new SigninResponse(new URL(window.location.href).searchParams); - } async componentDidMount() { if (this.response.error) return; - + window.localStorage.removeItem('auth_fail'); + let code_verifier = '?'; // get code verifier for (const key in localStorage) { @@ -50,11 +49,19 @@ export default class LoggedIn extends React.Component { } const response = await User.login({...this.response, code_verifier}); + + if (response.error) { + // pass the data to LoginPage + window.localStorage.setItem('auth_fail', JSON.stringify(response)); + window.location.href = '/login'; + return; + } + if (response.new_user) { // TODO: Make the page - useNavigate('/register'); + window.location.href = '/register'; } else { - useNavigate('/'); + window.location.href = '/'; } } diff --git a/pairent_frontend_react/src/pages/LoginPage/index.jsx b/pairent_frontend_react/src/pages/LoginPage/index.jsx index 40b5ba4..578d891 100644 --- a/pairent_frontend_react/src/pages/LoginPage/index.jsx +++ b/pairent_frontend_react/src/pages/LoginPage/index.jsx @@ -45,9 +45,11 @@ export default class LoginPage extends React.Component { super(props); this.state = { - loading: false + loading: false, + error: JSON.parse(window.localStorage.getItem('auth_fail')) } + window.localStorage.removeItem('auth_fail'); this.openid = this.openid.bind(this); } @@ -56,12 +58,11 @@ export default class LoginPage extends React.Component { this.setState({loading: true}); OpenID.Log.setLogger(console); - OpenID.Log.setLevel(OpenID.Log.DEBUG); + OpenID.Log.setLevel(OpenID.Log.NONE); let client = new OpenID.UserManager(OIDCConfig); client.signinRedirect(); - } render() { @@ -84,6 +85,21 @@ export default class LoginPage extends React.Component { Вход осуществляется только через
Систему Единого Входа ВВГУ + { + this.state.error ? + + Произошла ошибка: { this.state.error.error } + { + this.state.error.error_description ? + <> +
+ {this.state.error.error_description} + + : null + } +
+ : null + } );