login kept in memory
This commit is contained in:
parent
ae0eb2c65a
commit
3c5b60e1aa
@ -2,6 +2,7 @@ import { readFileSync } from 'fs';
|
|||||||
|
|
||||||
export type ServerConfig = {
|
export type ServerConfig = {
|
||||||
port: number;
|
port: number;
|
||||||
|
origin: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MongoConfig = {
|
export type MongoConfig = {
|
||||||
|
@ -16,10 +16,21 @@ class Server {
|
|||||||
|
|
||||||
this.app = express();
|
this.app = express();
|
||||||
this.app.use(express.json());
|
this.app.use(express.json());
|
||||||
this.app.use(cors());
|
this.app.use(
|
||||||
|
cors({
|
||||||
|
maxAge: 86400,
|
||||||
|
credentials: true,
|
||||||
|
origin: this.config.origin,
|
||||||
|
}),
|
||||||
|
);
|
||||||
this.app.use(RequestId());
|
this.app.use(RequestId());
|
||||||
this.app.use(
|
this.app.use(
|
||||||
session({ secret: randomUUID(), cookie: { maxAge: 1000 * 3600 * 24 } }),
|
session({
|
||||||
|
secret: randomUUID(),
|
||||||
|
cookie: { maxAge: 1000 * 3600 * 24 },
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: false,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
//this.app.use(checkPermissions());
|
//this.app.use(checkPermissions());
|
||||||
this.app.use(getRoutes(services));
|
this.app.use(getRoutes(services));
|
||||||
|
@ -27,7 +27,7 @@ function LogoutHandler(services: Services): RequestHandler {
|
|||||||
req.session.user = null;
|
req.session.user = null;
|
||||||
res.status(204).send();
|
res.status(204).send();
|
||||||
} else {
|
} else {
|
||||||
next({ message: 'not logged in' });
|
next({ status: 401, message: 'not logged in' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ function serve() {
|
|||||||
export default {
|
export default {
|
||||||
input: 'src/main.ts',
|
input: 'src/main.ts',
|
||||||
output: {
|
output: {
|
||||||
sourcemap: true,
|
sourcemap: !production,
|
||||||
format: 'iife',
|
format: 'iife',
|
||||||
name: 'app',
|
name: 'app',
|
||||||
file: 'public/build/bundle.js',
|
file: 'public/build/bundle.js',
|
||||||
@ -73,6 +73,7 @@ export default {
|
|||||||
}),
|
}),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
replace({
|
replace({
|
||||||
|
preventAssignment: true,
|
||||||
'process.env.APIURL': production ? '"/api"' : '"http://localhost:8000"',
|
'process.env.APIURL': production ? '"/api"' : '"http://localhost:8000"',
|
||||||
'process.env.CORS': production ? 'false' : 'true',
|
'process.env.CORS': production ? 'false' : 'true',
|
||||||
}),
|
}),
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
import Test3D from './pages/test3D.svelte';
|
import Test3D from './pages/test3D.svelte';
|
||||||
import Login from './pages/Login.svelte';
|
import Login from './pages/Login.svelte';
|
||||||
|
import Profile from './pages/Profile.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Router>
|
<Router>
|
||||||
@ -13,4 +14,7 @@
|
|||||||
<Route path="/login">
|
<Route path="/login">
|
||||||
<Login />
|
<Login />
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route path="/profile">
|
||||||
|
<Profile />
|
||||||
|
</Route>
|
||||||
</Router>
|
</Router>
|
||||||
|
55
www/src/components/NavBar.svelte
Normal file
55
www/src/components/NavBar.svelte
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Link } from 'svelte-navigator';
|
||||||
|
import { currentUser } from '../store/user';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<nav class="border row">
|
||||||
|
{#if $currentUser === null}
|
||||||
|
<Link to="/" class="col-fill col">
|
||||||
|
<div class="nav-button" id="home" />
|
||||||
|
</Link>
|
||||||
|
<Link to="/login" class="col-fill col">
|
||||||
|
<div class="nav-button" id="login" />
|
||||||
|
</Link>
|
||||||
|
{:else}
|
||||||
|
<Link to="/" class="col-fill col">
|
||||||
|
<div class="nav-button" id="home" />
|
||||||
|
</Link>
|
||||||
|
<Link to="/profile" class="col-fill col">
|
||||||
|
<div class="nav-button" id="profile" />
|
||||||
|
</Link>
|
||||||
|
<Link to="/test" class="col-fill col">
|
||||||
|
<div class="nav-button" id="test" />
|
||||||
|
</Link>
|
||||||
|
{/if}
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
nav {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
margin: 3px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.nav-button {
|
||||||
|
height: 30px;
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.nav-button#home {
|
||||||
|
background-image: url('/images/mosaic-of-four-hand-drawn-squares-tiles.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
div.nav-button#login {
|
||||||
|
background-image: url('/images/next-user-hand-drawn-interface-symbol.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
div.nav-button#profile {
|
||||||
|
background-image: url('/images/id-hand-drawn-symbol.png');
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,38 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { Link } from 'svelte-navigator';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<nav class="border row">
|
|
||||||
<Link to="/" class="col-fill col">
|
|
||||||
<div class="nav-button" id="home" />
|
|
||||||
</Link>
|
|
||||||
<Link to="/login" class="col-fill col">
|
|
||||||
<div class="nav-button" id="login" />
|
|
||||||
</Link>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
nav {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
margin: 3px;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.nav-button {
|
|
||||||
height: 50px;
|
|
||||||
background-size: contain;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.nav-button#home {
|
|
||||||
background-image: url('/images/mosaic-of-four-hand-drawn-squares-tiles.png');
|
|
||||||
}
|
|
||||||
|
|
||||||
div.nav-button#login {
|
|
||||||
background-image: url('/images/next-user-hand-drawn-interface-symbol.png');
|
|
||||||
}
|
|
||||||
</style>
|
|
19
www/src/functions/localStorage.ts
Normal file
19
www/src/functions/localStorage.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
export function save(key: string, data: unknown) {
|
||||||
|
if (data) {
|
||||||
|
localStorage.setItem(key, JSON.stringify(data));
|
||||||
|
} else {
|
||||||
|
remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function remove(key: string) {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function read<T>(key: string) {
|
||||||
|
const data = localStorage.getItem(key);
|
||||||
|
if (data) {
|
||||||
|
return JSON.parse(data) as T;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
@ -8,7 +8,10 @@ export async function get<T>(route: string): Promise<T | null> {
|
|||||||
return request<T>('GET', route);
|
return request<T>('GET', route);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function post<T>(route: string, data: unknown): Promise<T | null> {
|
export async function post<T>(
|
||||||
|
route: string,
|
||||||
|
data?: unknown,
|
||||||
|
): Promise<T | null> {
|
||||||
return request<T>('POST', route, data);
|
return request<T>('POST', route, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,12 +28,13 @@ async function request<T>(
|
|||||||
headers: {
|
headers: {
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
},
|
},
|
||||||
|
credentials: process.env.CORS ? 'include' : 'same-origin',
|
||||||
mode: process.env.CORS ? 'cors' : 'same-origin',
|
mode: process.env.CORS ? 'cors' : 'same-origin',
|
||||||
method: method,
|
method: method,
|
||||||
body: data ? JSON.stringify(data) : null,
|
body: data ? JSON.stringify(data) : null,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok && response.status !== 204) {
|
||||||
return response.json() as T;
|
return response.json() as T;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,8 +1,22 @@
|
|||||||
import type { LoginUserBody, UserInfo } from '@core';
|
import type { CreateUserBody, LoginUserBody, UserInfo } from '@core';
|
||||||
import { post } from './request';
|
import { post, get } from './request';
|
||||||
import { currentUser } from '../store/user';
|
import { currentUser } from '../store/user';
|
||||||
|
|
||||||
export async function login(raw: LoginUserBody) {
|
export async function login(raw: LoginUserBody) {
|
||||||
const user = await post<UserInfo>('/user/login', raw);
|
const user = await post<UserInfo>('/user/login', raw);
|
||||||
currentUser.set(user);
|
currentUser.set(user);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function logout() {
|
||||||
|
await post('/user/logout');
|
||||||
|
currentUser.set(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function read(uuid: string) {
|
||||||
|
const user = await get<UserInfo>(`/user/read/${uuid}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function create(raw: CreateUserBody) {
|
||||||
|
const user = await post<UserInfo>('/user/create', raw);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import App from './App.svelte';
|
|||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
target: document.body,
|
target: document.body,
|
||||||
props: {},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { LoginUserBody } from '@core';
|
import type { LoginUserBody } from '@core';
|
||||||
import NavBar from '../components/navBar.svelte';
|
import NavBar from '../components/NavBar.svelte';
|
||||||
import { Form, Input, Button } from 'spaper';
|
import { Form, Input, Button } from 'spaper';
|
||||||
import { login } from '../functions/user';
|
import { login } from '../functions/user';
|
||||||
import { currentUser } from '../store/user';
|
import { useNavigate } from 'svelte-navigator';
|
||||||
|
|
||||||
const user: LoginUserBody = {
|
const user: LoginUserBody = {
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const loginHandler = async () => {
|
||||||
|
const result = await login(user);
|
||||||
|
if (result) {
|
||||||
|
navigate('/');
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="row" id="container">
|
<div class="row" id="container">
|
||||||
@ -16,25 +25,23 @@
|
|||||||
<Input
|
<Input
|
||||||
placeholder="username"
|
placeholder="username"
|
||||||
class="row col-8"
|
class="row col-8"
|
||||||
|
autocomplete
|
||||||
bind:value={user.username}
|
bind:value={user.username}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
placeholder="password"
|
placeholder="password"
|
||||||
type="password"
|
type="password"
|
||||||
|
autocomplete
|
||||||
class="row col-8"
|
class="row col-8"
|
||||||
bind:value={user.password}
|
bind:value={user.password}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="secondary"
|
type="secondary"
|
||||||
class="row sm-2 col-4"
|
class="row sm-2 col-4"
|
||||||
block
|
block
|
||||||
on:click={() => login(user)}>Sign in</Button
|
on:click={() => loginHandler()}>Sign in</Button
|
||||||
>
|
>
|
||||||
</Form>
|
</Form>
|
||||||
{$currentUser?.uuid}
|
|
||||||
{$currentUser?.username}
|
|
||||||
{$currentUser?.role}
|
|
||||||
</div>
|
</div>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
|
|
||||||
|
23
www/src/pages/Profile.svelte
Normal file
23
www/src/pages/Profile.svelte
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import NavBar from '../components/NavBar.svelte';
|
||||||
|
import { currentUser } from '../store/user';
|
||||||
|
import { Button } from 'spaper';
|
||||||
|
import { logout } from '../functions/user';
|
||||||
|
import { useNavigate } from 'svelte-navigator';
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const logoutHandler = async () => {
|
||||||
|
await logout();
|
||||||
|
navigate('/');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Button type="danger" block on:click={() => logoutHandler()}>Logout</Button>
|
||||||
|
{$currentUser?.uuid}
|
||||||
|
{$currentUser?.username}
|
||||||
|
{$currentUser?.role}
|
||||||
|
<NavBar />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import NavBar from '../components/navBar.svelte';
|
import NavBar from '../components/NavBar.svelte';
|
||||||
import { beforeUpdate, afterUpdate, onMount, onDestroy } from 'svelte';
|
import { beforeUpdate, afterUpdate, onMount, onDestroy } from 'svelte';
|
||||||
import * as Three from 'three';
|
import * as Three from 'three';
|
||||||
|
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
import type { UserInfo } from '@core';
|
import type { UserInfo } from '@core';
|
||||||
|
import { save, read } from '../functions/localStorage';
|
||||||
|
|
||||||
export const currentUser = writable<UserInfo | null>(null);
|
export const currentUser = writable<UserInfo | null>(read<UserInfo>('user'));
|
||||||
|
currentUser.subscribe((user) => {
|
||||||
|
save('user', user);
|
||||||
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"sourceMap": false,
|
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"baseUrl": "./src",
|
"baseUrl": "./src",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user