Updated login refresh logic, working on tile grid
This commit is contained in:
@@ -340,6 +340,40 @@ async fn me(auth: JwtAuth) -> HttpResponse {
|
|||||||
HttpResponse::Ok().json(auth)
|
HttpResponse::Ok().json(auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/check-session")]
|
||||||
|
async fn check_session(req: HttpRequest) -> HttpResponse {
|
||||||
|
// If there is a access_token cookie, check if it is valid
|
||||||
|
let has_session = match req.cookie("access_token") {
|
||||||
|
Some(cookie) => {
|
||||||
|
let access_token = cookie.value().to_string();
|
||||||
|
let public_key = env::var("ACCESS_TOKEN_PUBLIC_KEY")
|
||||||
|
.expect("ACCESS_TOKEN_PUBLIC_KEY must be set");
|
||||||
|
match verify_token(&access_token, &public_key) {
|
||||||
|
Ok(_) => true,
|
||||||
|
Err(_) => false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => false
|
||||||
|
};
|
||||||
|
if !has_session {
|
||||||
|
// If there is a refresh_token cookie, check if it is valid
|
||||||
|
match req.cookie("refresh_token") {
|
||||||
|
Some(cookie) => {
|
||||||
|
let refresh_token = cookie.value().to_string();
|
||||||
|
let public_key = env::var("REFRESH_TOKEN_PUBLIC_KEY")
|
||||||
|
.expect("REFRESH_TOKEN_PUBLIC_KEY must be set");
|
||||||
|
match verify_token(&refresh_token, &public_key) {
|
||||||
|
Ok(_) => return HttpResponse::Ok().json(true),
|
||||||
|
Err(_) => return HttpResponse::Ok().json(false)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
None => return HttpResponse::Ok().json(false)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return HttpResponse::Ok().json(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/roles")]
|
#[get("/roles")]
|
||||||
async fn roles() -> HttpResponse {
|
async fn roles() -> HttpResponse {
|
||||||
HttpResponse::Ok().json(vec!["admin", "user"])
|
HttpResponse::Ok().json(vec!["admin", "user"])
|
||||||
@@ -363,5 +397,6 @@ pub fn init_routes(config: &mut web::ServiceConfig) {
|
|||||||
.service(logout)
|
.service(logout)
|
||||||
.service(me)
|
.service(me)
|
||||||
.service(roles)
|
.service(roles)
|
||||||
|
.service(check_session)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -42,6 +42,15 @@ export async function me(): Promise<ResponseAuth | undefined> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function hasSession(): Promise<boolean> {
|
||||||
|
const response = await getRequest('auth/check-session');
|
||||||
|
if (response?.status === 200) {
|
||||||
|
return response?.json();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes the logged_in cookie every interval. By default, the interval is 14 minutes.
|
* Refreshes the logged_in cookie every interval. By default, the interval is 14 minutes.
|
||||||
* @param interval
|
* @param interval
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { login, register, refreshLoggedIn } from '@/api/auth';
|
import { login, register } from '@/api/auth';
|
||||||
import { User } from '@/api/auth.types';
|
import { User } from '@/api/auth.types';
|
||||||
import {
|
import {
|
||||||
Modal,
|
Modal,
|
||||||
@@ -146,7 +146,6 @@ export function HeaderModal({ type, toggle, setUser, setRefreshId }: HeaderModal
|
|||||||
const loginResponse = await login(values.email, values.password);
|
const loginResponse = await login(values.email, values.password);
|
||||||
if (loginResponse) {
|
if (loginResponse) {
|
||||||
setUser(loginResponse.user);
|
setUser(loginResponse.user);
|
||||||
setRefreshId(refreshLoggedIn());
|
|
||||||
onClose();
|
onClose();
|
||||||
notifications.update({
|
notifications.update({
|
||||||
id,
|
id,
|
||||||
@@ -222,7 +221,6 @@ export function HeaderModal({ type, toggle, setUser, setRefreshId }: HeaderModal
|
|||||||
const response = await login(values.email, values.password);
|
const response = await login(values.email, values.password);
|
||||||
if (response) {
|
if (response) {
|
||||||
setUser(response.user);
|
setUser(response.user);
|
||||||
setRefreshId(refreshLoggedIn());
|
|
||||||
onClose();
|
onClose();
|
||||||
} else {
|
} else {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import './header.css';
|
|||||||
import { Avatar, Button, Card, Center, FileButton, Grid, Group, Menu, Text, UnstyledButton } from '@mantine/core';
|
import { Avatar, Button, Card, Center, FileButton, Grid, Group, Menu, Text, UnstyledButton } from '@mantine/core';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { logout, refresh, refreshLoggedIn } from '@/api/auth';
|
import { hasSession, logout, refresh, refreshLoggedIn } from '@/api/auth';
|
||||||
import { useToggle } from '@mantine/hooks';
|
import { useToggle } from '@mantine/hooks';
|
||||||
import { HeaderModal } from './HeaderModal';
|
import { HeaderModal } from './HeaderModal';
|
||||||
import { HeaderItem, headerItems } from './headerItems';
|
import { HeaderItem, headerItems } from './headerItems';
|
||||||
@@ -14,6 +14,7 @@ import { userState } from '@/state/auth';
|
|||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
import { getPicture, setPicture } from '@/api/users';
|
import { getPicture, setPicture } from '@/api/users';
|
||||||
import { BsChevronDown } from 'react-icons/bs';
|
import { BsChevronDown } from 'react-icons/bs';
|
||||||
|
import { User } from '@/api/auth.types';
|
||||||
|
|
||||||
export default function Header() {
|
export default function Header() {
|
||||||
const pathName = usePathname();
|
const pathName = usePathname();
|
||||||
@@ -25,23 +26,33 @@ export default function Header() {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!user || !Cookies.get('logged_in')) {
|
if (!user) {
|
||||||
refresh().then((response) => {
|
hasSession().then((response) => {
|
||||||
if (response) {
|
if (response) {
|
||||||
setRefreshId(refreshLoggedIn());
|
refresh().then((response) => {
|
||||||
setUser(response.user);
|
if (response) {
|
||||||
if (response.user.profile_picture) {
|
setUser(response.user);
|
||||||
getPicture().then((response) => {
|
updateUser(response.user);
|
||||||
if (response) {
|
}
|
||||||
setProfilePicture(response as File);
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
|
function updateUser(user?: User) {
|
||||||
|
if (!refreshId) {
|
||||||
|
setRefreshId(refreshLoggedIn());
|
||||||
|
}
|
||||||
|
if (user) {
|
||||||
|
getPicture().then((response) => {
|
||||||
|
if (response) {
|
||||||
|
setProfilePicture(response as File);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<nav className='navbar'>
|
<nav className='navbar'>
|
||||||
@@ -159,6 +170,8 @@ export default function Header() {
|
|||||||
await logout();
|
await logout();
|
||||||
Cookies.remove('logged_in');
|
Cookies.remove('logged_in');
|
||||||
setUser(undefined);
|
setUser(undefined);
|
||||||
|
clearInterval(refreshId);
|
||||||
|
setRefreshId(undefined);
|
||||||
setProfilePicture(null);
|
setProfilePicture(null);
|
||||||
if (refreshId) {
|
if (refreshId) {
|
||||||
clearInterval(refreshId);
|
clearInterval(refreshId);
|
||||||
@@ -196,13 +209,7 @@ export default function Header() {
|
|||||||
toggle={toggle}
|
toggle={toggle}
|
||||||
setUser={(u) => {
|
setUser={(u) => {
|
||||||
setUser(u);
|
setUser(u);
|
||||||
if (u.profile_picture) {
|
updateUser(u);
|
||||||
getPicture().then((response) => {
|
|
||||||
if (response) {
|
|
||||||
setProfilePicture(response as File);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
setRefreshId={setRefreshId}
|
setRefreshId={setRefreshId}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Graphics, Stage, Text } from '@pixi/react';
|
import { Graphics, Stage } from '@pixi/react';
|
||||||
import { Graphics as PixiGraphics } from '@pixi/graphics';
|
import { Graphics as PixiGraphics } from '@pixi/graphics';
|
||||||
import { MouseEvent, WheelEvent, useCallback, useEffect, useState } from 'react';
|
import { MouseEvent, WheelEvent, useCallback, useEffect, useState } from 'react';
|
||||||
import TileControls, { EditTool, Tool, defaultColors } from './TileControls';
|
import TileControls, { EditTool, Tool, defaultColors } from './TileControls';
|
||||||
import { Box } from '@mantine/core';
|
import { Box } from '@mantine/core';
|
||||||
import { TextStyle } from 'pixi.js';
|
|
||||||
|
|
||||||
interface SquareEdit {
|
interface SquareEdit {
|
||||||
x: number;
|
x: number;
|
||||||
@@ -31,24 +30,21 @@ export default function TileGrid() {
|
|||||||
const [edits, setEdits] = useState<SquareEdit[]>([]);
|
const [edits, setEdits] = useState<SquareEdit[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (window) {
|
// Prevent context menu from appearing on right click
|
||||||
// window.addEventListener(
|
function handleContextmenu(e: any) {
|
||||||
// 'wheel',
|
e.preventDefault()
|
||||||
// (event) => {
|
|
||||||
// event.preventDefault();
|
|
||||||
// },
|
|
||||||
// { passive: false }
|
|
||||||
// );
|
|
||||||
// // Disable right click context menu
|
|
||||||
// window.addEventListener(
|
|
||||||
// 'contextmenu',
|
|
||||||
// (event) => {
|
|
||||||
// event.preventDefault();
|
|
||||||
// },
|
|
||||||
// { passive: false }
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
}, []);
|
document.addEventListener('contextmenu', handleContextmenu)
|
||||||
|
// Prevent scrollwheel from scrolling page
|
||||||
|
function handleScroll(e: any) {
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
document.addEventListener('wheel', handleScroll, { passive: false })
|
||||||
|
return function cleanup() {
|
||||||
|
document.removeEventListener('contextmenu', handleContextmenu)
|
||||||
|
document.removeEventListener('wheel', handleScroll)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
const drawGrid = useCallback(
|
const drawGrid = useCallback(
|
||||||
(g: PixiGraphics) => {
|
(g: PixiGraphics) => {
|
||||||
@@ -65,7 +61,7 @@ export default function TileGrid() {
|
|||||||
[gridSize, zoom]
|
[gridSize, zoom]
|
||||||
);
|
);
|
||||||
|
|
||||||
const drawEdits = useCallback(
|
const drawGridEdits = useCallback(
|
||||||
(g: PixiGraphics) => {
|
(g: PixiGraphics) => {
|
||||||
g.clear();
|
g.clear();
|
||||||
edits.forEach((edit) => {
|
edits.forEach((edit) => {
|
||||||
@@ -77,24 +73,10 @@ export default function TileGrid() {
|
|||||||
[edits, zoom]
|
[edits, zoom]
|
||||||
);
|
);
|
||||||
|
|
||||||
function clickEvent(e: MouseEvent) {
|
|
||||||
setMouseDown(true);
|
|
||||||
setLastPosition({ x: e.clientX, y: e.clientY });
|
|
||||||
if (tool == Tool.ZOOM) {
|
|
||||||
handleZoom(e.button === 0 ? -100 : 100, e.clientX, e.clientY);
|
|
||||||
} else if (tool == Tool.EDIT) {
|
|
||||||
if (editTool === EditTool.SQUARE) {
|
|
||||||
drawSquare(e.button, e.clientX, e.clientY);
|
|
||||||
} else if (editTool === EditTool.CIRCLE) {
|
|
||||||
// handle circle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawSquare(button: number, clientX: number, clientY: number) {
|
function drawSquare(button: number, clientX: number, clientY: number) {
|
||||||
// Calculate tile coordinates
|
|
||||||
const x = Math.floor((clientX - position.x) / (32 * zoom));
|
const x = Math.floor((clientX - position.x) / (32 * zoom));
|
||||||
const y = Math.floor((clientY - position.y) / (32 * zoom));
|
// TODO: Fix y offset, currently appears to be 2 tiles down from mouse
|
||||||
|
const y = Math.floor((clientY - position.y) / (32 * zoom)) - 2;
|
||||||
if (button === 1) {
|
if (button === 1) {
|
||||||
// Add new edit if left mouse button is pressed
|
// Add new edit if left mouse button is pressed
|
||||||
setEdits([...edits, { x, y, color: colors[selectedColor] }]);
|
setEdits([...edits, { x, y, color: colors[selectedColor] }]);
|
||||||
@@ -104,6 +86,20 @@ export default function TileGrid() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clickEvent(e: MouseEvent, isMouseDown: boolean) {
|
||||||
|
setMouseDown(isMouseDown);
|
||||||
|
setLastPosition({ x: e.clientX, y: e.clientY });
|
||||||
|
if (isMouseDown) {
|
||||||
|
if (tool == Tool.ZOOM) {
|
||||||
|
handleZoom(e.buttons === 1 ? -100 : 100, e.clientX, e.clientY);
|
||||||
|
} else if (tool == Tool.EDIT && editTool === EditTool.SQUARE) {
|
||||||
|
drawSquare(e.buttons, e.clientX, e.clientY);
|
||||||
|
} else if (editTool === EditTool.CIRCLE) {
|
||||||
|
// handle circle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function moveEvent(e: MouseEvent) {
|
function moveEvent(e: MouseEvent) {
|
||||||
if (mouseDown) {
|
if (mouseDown) {
|
||||||
if (tool == Tool.HAND || e.buttons == 4) {
|
if (tool == Tool.HAND || e.buttons == 4) {
|
||||||
@@ -116,12 +112,10 @@ export default function TileGrid() {
|
|||||||
dy = Math.max(dy, -gridSize.height * zoom + height);
|
dy = Math.max(dy, -gridSize.height * zoom + height);
|
||||||
setPosition({ x: dx, y: dy });
|
setPosition({ x: dx, y: dy });
|
||||||
setLastPosition({ x: e.clientX, y: e.clientY });
|
setLastPosition({ x: e.clientX, y: e.clientY });
|
||||||
} else if (tool === Tool.EDIT) {
|
} else if (tool === Tool.EDIT && editTool === EditTool.SQUARE) {
|
||||||
if (editTool === EditTool.SQUARE) {
|
|
||||||
drawSquare(e.buttons, e.clientX, e.clientY);
|
drawSquare(e.buttons, e.clientX, e.clientY);
|
||||||
} else if (editTool === EditTool.CIRCLE) {
|
} else if (tool === Tool.EDIT && editTool === EditTool.CIRCLE) {
|
||||||
// handle circle
|
// handle circle
|
||||||
}
|
|
||||||
} else if (tool === Tool.TOKEN) {
|
} else if (tool === Tool.TOKEN) {
|
||||||
// handle token
|
// handle token
|
||||||
}
|
}
|
||||||
@@ -141,11 +135,15 @@ export default function TileGrid() {
|
|||||||
}
|
}
|
||||||
newZoom = Math.min(newZoom, 3);
|
newZoom = Math.min(newZoom, 3);
|
||||||
newZoom = Math.max(newZoom, 0.6);
|
newZoom = Math.max(newZoom, 0.6);
|
||||||
console.log(newZoom);
|
|
||||||
setZoom(newZoom);
|
setZoom(newZoom);
|
||||||
// Adjust position to zoom in on mouse position
|
// Adjust position to zoom in on mouse position
|
||||||
const dx = (position.x - clientX) * (newZoom / zoom) + clientX;
|
let dx = (position.x - clientX) * (newZoom / zoom) + clientX;
|
||||||
const dy = (position.y - clientY) * (newZoom / zoom) + clientY;
|
let dy = (position.y - clientY) * (newZoom / zoom) + clientY;
|
||||||
|
// Prevent coordinates from going out of bounds
|
||||||
|
dx = Math.min(dx, 0);
|
||||||
|
dx = Math.max(dx, -gridSize.width * newZoom + width);
|
||||||
|
dy = Math.min(dy, 0);
|
||||||
|
dy = Math.max(dy, -gridSize.height * newZoom + height);
|
||||||
setPosition({ x: dx, y: dy });
|
setPosition({ x: dx, y: dy });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,13 +156,13 @@ export default function TileGrid() {
|
|||||||
backgroundColor: 0x333333,
|
backgroundColor: 0x333333,
|
||||||
antialias: false
|
antialias: false
|
||||||
}}
|
}}
|
||||||
onMouseDown={(e) => clickEvent(e)}
|
onMouseDown={(e) => clickEvent(e, true)}
|
||||||
onMouseUp={() => setMouseDown(false)}
|
onMouseUp={(e) => clickEvent(e, false)}
|
||||||
onMouseMove={(e) => moveEvent(e)}
|
onMouseMove={(e) => moveEvent(e)}
|
||||||
onWheel={(e) => zoomEvent(e)}
|
onWheel={(e) => zoomEvent(e)}
|
||||||
>
|
>
|
||||||
<Graphics x={position.x} y={position.y} draw={drawGrid} />
|
<Graphics x={position.x} y={position.y} draw={drawGrid} />
|
||||||
<Graphics x={position.x} y={position.y} draw={drawEdits} />
|
<Graphics x={position.x} y={position.y} draw={drawGridEdits} />
|
||||||
</Stage>
|
</Stage>
|
||||||
<TileControls
|
<TileControls
|
||||||
tool={tool}
|
tool={tool}
|
||||||
|
|||||||
@@ -5,8 +5,3 @@ export const userState = atom({
|
|||||||
key: 'userState',
|
key: 'userState',
|
||||||
default: undefined as User | undefined
|
default: undefined as User | undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
export const isAuthenticatedState = atom({
|
|
||||||
key: 'isAuthenticatedState',
|
|
||||||
default: false
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user