user_registration #10
@ -144,7 +144,7 @@ impl<'r> FromRequest<'r> for User {
|
|||||||
let id = token.claims.uid;
|
let id = token.claims.uid;
|
||||||
|
|
||||||
let conn = req.guard::<DbConn>().await.unwrap();
|
let conn = req.guard::<DbConn>().await.unwrap();
|
||||||
return match get_user(conn, id).await {
|
return match get_user(&conn, id).await {
|
||||||
Ok(o) => Outcome::Success(o),
|
Ok(o) => Outcome::Success(o),
|
||||||
Err(_) => Outcome::Forward(()),
|
Err(_) => Outcome::Forward(()),
|
||||||
};
|
};
|
||||||
@ -354,8 +354,32 @@ pub async fn gamenights_delete_json_unauthorized() -> ApiResponseVariant {
|
|||||||
ApiResponseVariant::Status(Status::Unauthorized)
|
ApiResponseVariant::Status(Status::Unauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/register", format = "application/json", data = "<register_json>")]
|
#[post(
|
||||||
pub async fn register_post_json(conn: DbConn, register_json: Json<Register>) -> ApiResponseVariant {
|
"/register/<registration_token>",
|
||||||
|
format = "application/json",
|
||||||
|
data = "<register_json>"
|
||||||
|
)]
|
||||||
|
pub async fn register_post_json(
|
||||||
|
conn: DbConn,
|
||||||
|
config: &State<AppConfig>,
|
||||||
|
register_json: Json<Register>,
|
||||||
|
registration_token: String,
|
||||||
|
) -> ApiResponseVariant {
|
||||||
|
let token = match schema::admin::get_registration_token(&conn, registration_token).await {
|
||||||
|
Ok(res) => res,
|
||||||
|
Err(error) => {
|
||||||
|
return ApiResponseVariant::Value(json!(ApiResponse::error(error.to_string())))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(expiry) = token.expires {
|
||||||
|
if expiry < Utc::now() {
|
||||||
|
return ApiResponseVariant::Value(json!(ApiResponse::error(
|
||||||
|
"Registration token has expired".to_string()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let register = register_json.into_inner();
|
let register = register_json.into_inner();
|
||||||
let register_clone = register.clone();
|
let register_clone = register.clone();
|
||||||
match conn
|
match conn
|
||||||
@ -366,11 +390,25 @@ pub async fn register_post_json(conn: DbConn, register_json: Json<Register>) ->
|
|||||||
Err(error) => {
|
Err(error) => {
|
||||||
return ApiResponseVariant::Value(json!(ApiResponse::error(error.to_string())))
|
return ApiResponseVariant::Value(json!(ApiResponse::error(error.to_string())))
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let user = match insert_user(&conn, register).await {
|
||||||
|
Ok(user) => user,
|
||||||
|
Err(err) => return ApiResponseVariant::Value(json!(ApiResponse::error(err.to_string()))),
|
||||||
|
};
|
||||||
|
|
||||||
|
if token.single_use {
|
||||||
|
match schema::admin::delete_registration_token(&conn, token.id).await {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(err) => {
|
||||||
|
return ApiResponseVariant::Value(json!(ApiResponse::error(err.to_string())))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match insert_user(conn, register).await {
|
match create_jwt_token(&user, config) {
|
||||||
Ok(_) => ApiResponseVariant::Value(json!(ApiResponse::SUCCES)),
|
Ok(token) => ApiResponseVariant::Value(json!(ApiResponse::login_response(user, token))),
|
||||||
Err(err) => ApiResponseVariant::Value(json!(ApiResponse::error(err.to_string()))),
|
Err(error) => ApiResponseVariant::Value(json!(ApiResponse::error(error.to_string()))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,6 +419,24 @@ struct Claims {
|
|||||||
role: Role,
|
role: Role,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_jwt_token(
|
||||||
|
user: &User,
|
||||||
|
config: &State<AppConfig>,
|
||||||
|
) -> Result<String, jsonwebtoken::errors::Error> {
|
||||||
|
let my_claims = Claims {
|
||||||
|
exp: Utc::now().timestamp() + chrono::Duration::days(7).num_seconds(),
|
||||||
|
uid: user.id,
|
||||||
|
role: user.role,
|
||||||
|
};
|
||||||
|
|
||||||
|
let secret = &config.inner().jwt_secret;
|
||||||
|
encode(
|
||||||
|
&Header::default(),
|
||||||
|
&my_claims,
|
||||||
|
&EncodingKey::from_secret(secret.as_bytes()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[post("/login", format = "application/json", data = "<login_json>")]
|
#[post("/login", format = "application/json", data = "<login_json>")]
|
||||||
pub async fn login_post_json(
|
pub async fn login_post_json(
|
||||||
conn: DbConn,
|
conn: DbConn,
|
||||||
@ -397,18 +453,7 @@ pub async fn login_post_json(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let user = login_result.user.unwrap();
|
let user = login_result.user.unwrap();
|
||||||
let my_claims = Claims {
|
match create_jwt_token(&user, config) {
|
||||||
exp: Utc::now().timestamp() + chrono::Duration::days(7).num_seconds(),
|
|
||||||
uid: user.id,
|
|
||||||
role: user.role,
|
|
||||||
};
|
|
||||||
|
|
||||||
let secret = &config.inner().jwt_secret;
|
|
||||||
match encode(
|
|
||||||
&Header::default(),
|
|
||||||
&my_claims,
|
|
||||||
&EncodingKey::from_secret(secret.as_bytes()),
|
|
||||||
) {
|
|
||||||
Ok(token) => {
|
Ok(token) => {
|
||||||
ApiResponseVariant::Value(json!(ApiResponse::login_response(user, token)))
|
ApiResponseVariant::Value(json!(ApiResponse::login_response(user, token)))
|
||||||
}
|
}
|
||||||
@ -560,7 +605,7 @@ pub async fn delete_registration_tokens(
|
|||||||
if user.role != Role::Admin {
|
if user.role != Role::Admin {
|
||||||
return ApiResponseVariant::Status(Status::Unauthorized);
|
return ApiResponseVariant::Status(Status::Unauthorized);
|
||||||
}
|
}
|
||||||
|
|
||||||
let uuid = Uuid::parse_str(&gamenight_id).unwrap();
|
let uuid = Uuid::parse_str(&gamenight_id).unwrap();
|
||||||
match schema::admin::delete_registration_token(&conn, uuid).await {
|
match schema::admin::delete_registration_token(&conn, uuid).await {
|
||||||
Ok(_) => ApiResponseVariant::Value(json!(ApiResponse::SUCCES)),
|
Ok(_) => ApiResponseVariant::Value(json!(ApiResponse::SUCCES)),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::schema::{DatabaseError, DbConn};
|
use crate::schema::{DatabaseError, DbConn};
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use diesel::{QueryDsl, RunQueryDsl, ExpressionMethods};
|
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@ -52,3 +52,16 @@ pub async fn delete_registration_token(conn: &DbConn, id: Uuid) -> Result<usize,
|
|||||||
})
|
})
|
||||||
.await?)
|
.await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_registration_token(
|
||||||
|
conn: &DbConn,
|
||||||
|
token: String,
|
||||||
|
) -> Result<RegistrationToken, DatabaseError> {
|
||||||
|
Ok(conn
|
||||||
|
.run(|c| {
|
||||||
|
registration_tokens::table
|
||||||
|
.filter(registration_tokens::token.eq(token))
|
||||||
|
.first(c)
|
||||||
|
})
|
||||||
|
.await?)
|
||||||
|
}
|
||||||
|
@ -86,7 +86,7 @@ pub struct Register {
|
|||||||
pub password_repeat: String,
|
pub password_repeat: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn insert_user(conn: DbConn, new_user: Register) -> Result<usize, DatabaseError> {
|
pub async fn insert_user(conn: &DbConn, new_user: Register) -> Result<User, DatabaseError> {
|
||||||
let salt = SaltString::generate(&mut OsRng);
|
let salt = SaltString::generate(&mut OsRng);
|
||||||
|
|
||||||
let argon2 = Argon2::default();
|
let argon2 = Argon2::default();
|
||||||
@ -114,7 +114,8 @@ pub async fn insert_user(conn: DbConn, new_user: Register) -> Result<usize, Data
|
|||||||
user_id: id,
|
user_id: id,
|
||||||
password: password_hash,
|
password: password_hash,
|
||||||
})
|
})
|
||||||
.execute(c)
|
.execute(c)?;
|
||||||
|
users::table.filter(users::id.eq(id)).first::<User>(c)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?)
|
.await?)
|
||||||
@ -155,7 +156,7 @@ pub async fn login(conn: DbConn, login: Login) -> Result<LoginResult, DatabaseEr
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_user(conn: DbConn, id: Uuid) -> Result<User, DatabaseError> {
|
pub async fn get_user(conn: &DbConn, id: Uuid) -> Result<User, DatabaseError> {
|
||||||
Ok(conn
|
Ok(conn
|
||||||
.run(move |c| users::table.filter(users::id.eq(id)).first(c))
|
.run(move |c| users::table.filter(users::id.eq(id)).first(c))
|
||||||
.await?)
|
.await?)
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import './App.css';
|
import './App.css';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import MenuBar from './components/MenuBar';
|
import MenuBar from './components/MenuBar';
|
||||||
import Login from './components/Login';
|
import Login from './components/Login';
|
||||||
import Gamenights from './components/Gamenights';
|
import Gamenights from './components/Gamenights';
|
||||||
import Gamenight from './components/Gamenight';
|
import Gamenight from './components/Gamenight';
|
||||||
import AdminPanel from './components/AdminPanel';
|
import AdminPanel from './components/AdminPanel';
|
||||||
|
import Register from './components/Register';
|
||||||
|
|
||||||
import { get_gamenights, get_games, unpack_api_result, login } from './api/Api';
|
import { get_gamenights, get_games, unpack_api_result, login } from './api/Api';
|
||||||
|
|
||||||
@ -21,20 +22,21 @@ function App() {
|
|||||||
const handleLogin = (input) => {
|
const handleLogin = (input) => {
|
||||||
unpack_api_result(login(input), setFlashData)
|
unpack_api_result(login(input), setFlashData)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
setUser(result.user);
|
if(result !== undefined) {
|
||||||
localStorage.setItem(localStorageUserKey, JSON.stringify(result.user));
|
setUser(result.user);
|
||||||
})
|
localStorage.setItem(localStorageUserKey, JSON.stringify(result.user));
|
||||||
.then(() => setAppState('LoggedIn'))
|
setAppState('LoggedIn')
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(activeGamenightId !== null) {
|
if(activeGamenightId !== null) {
|
||||||
setAppState('GamenightDetails');
|
setAppState('GamenightDetails');
|
||||||
} else {
|
} else {
|
||||||
setAppState('LoggedIn')
|
setAppState(user === null ? 'LoggedOut' : 'LoggedIn')
|
||||||
}
|
}
|
||||||
|
}, [activeGamenightId, user])
|
||||||
}, [activeGamenightId])
|
|
||||||
|
|
||||||
const onLogout = () => {
|
const onLogout = () => {
|
||||||
setUser(null);
|
setUser(null);
|
||||||
@ -50,31 +52,47 @@ function App() {
|
|||||||
setAppState('UserPage')
|
setAppState('UserPage')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onRegister = () => {
|
||||||
|
setAppState('RegisterPage')
|
||||||
|
}
|
||||||
|
|
||||||
const onReset = () => {
|
const onReset = () => {
|
||||||
setAppState('LoggedIn')
|
setAppState(user === null ? 'LoggedOut' : 'LoggedIn')
|
||||||
|
}
|
||||||
|
|
||||||
|
const onRegistered = (user) => {
|
||||||
|
setUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
const setFlash = (data) => {
|
const setFlash = (data) => {
|
||||||
setFlashData(data);
|
setFlashData(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const refetchGamenights = () => {
|
const refetchGamenights = useCallback(() => {
|
||||||
setUser({...user});
|
unpack_api_result(get_gamenights(user.jwt), setFlashData)
|
||||||
};
|
.then(result => {
|
||||||
|
if (result !== undefined) {
|
||||||
|
setGamenights(result.gamenights);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (appState === 'LoggedIn') {
|
if (appState === 'LoggedIn') {
|
||||||
unpack_api_result(get_gamenights(user.jwt), setFlashData)
|
refetchGamenights()
|
||||||
.then(result => setGamenights(result.gamenights));
|
|
||||||
}
|
}
|
||||||
}, [appState])
|
}, [appState, refetchGamenights])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (appState === 'LoggedIn') {
|
if (appState === 'LoggedIn') {
|
||||||
unpack_api_result(get_games(user.jwt), setFlashData)
|
unpack_api_result(get_games(user.jwt), setFlashData)
|
||||||
.then(result => setGames(result.games));
|
.then(result => {
|
||||||
|
if (result !== undefined) {
|
||||||
|
setGames(result.games)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [appState])
|
}, [appState, user])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setUser(JSON.parse(localStorage.getItem(localStorageUserKey)));
|
setUser(JSON.parse(localStorage.getItem(localStorageUserKey)));
|
||||||
@ -82,12 +100,22 @@ function App() {
|
|||||||
|
|
||||||
let mainview;
|
let mainview;
|
||||||
if(appState === 'LoggedOut') {
|
if(appState === 'LoggedOut') {
|
||||||
return (
|
mainview = (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<Login onChange={handleLogin}/>
|
<Login onChange={handleLogin}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if(appState === 'GamenightDetails') {
|
} else if(appState === 'RegisterPage') {
|
||||||
|
mainview = (
|
||||||
|
<Register
|
||||||
|
onRegistered={onRegistered}
|
||||||
|
setFlash={setFlash}/>
|
||||||
|
);
|
||||||
|
} else if(appState === 'UserPage') {
|
||||||
|
mainview = (
|
||||||
|
<span>UserPage</span>
|
||||||
|
)
|
||||||
|
}else if(appState === 'GamenightDetails') {
|
||||||
mainview = (
|
mainview = (
|
||||||
<Gamenight
|
<Gamenight
|
||||||
gamenightId={activeGamenightId}
|
gamenightId={activeGamenightId}
|
||||||
@ -117,6 +145,7 @@ function App() {
|
|||||||
<MenuBar
|
<MenuBar
|
||||||
user={user}
|
user={user}
|
||||||
onUser={onUser}
|
onUser={onUser}
|
||||||
|
onRegister={onRegister}
|
||||||
onAdmin={onAdmin}
|
onAdmin={onAdmin}
|
||||||
onLogout={onLogout}
|
onLogout={onLogout}
|
||||||
onReset={onReset}/>
|
onReset={onReset}/>
|
||||||
|
@ -2,21 +2,18 @@
|
|||||||
import fetchResource from './FetchResource'
|
import fetchResource from './FetchResource'
|
||||||
|
|
||||||
export function unpack_api_result(promise, onError) {
|
export function unpack_api_result(promise, onError) {
|
||||||
promise.then(result => {
|
return promise.then(result => {
|
||||||
if(result.result !== 'Ok') {
|
if(result.result !== 'Ok') {
|
||||||
onError({
|
throw new Error(result.message);
|
||||||
type: 'Error',
|
|
||||||
message: result.message
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
onError({
|
onError({
|
||||||
type: 'Error',
|
type: 'Error',
|
||||||
message: `${error.status} ${error.message}`
|
message: `${error.status === null ?? error.status} ${error.message}`
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return promise;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_gamenights(token) {
|
export function get_gamenights(token) {
|
||||||
@ -116,4 +113,14 @@ export function delete_registration_token(token, registration_token_id) {
|
|||||||
'Authorization': `Bearer ${token}`,
|
'Authorization': `Bearer ${token}`,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function register(registration_token, input) {
|
||||||
|
return fetchResource(`api/register/${registration_token}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(input)
|
||||||
|
});
|
||||||
}
|
}
|
@ -47,11 +47,13 @@ function AddGameNight(props) {
|
|||||||
|
|
||||||
unpack_api_result(post_gamenight(input, props.user.jwt), props.setFlash)
|
unpack_api_result(post_gamenight(input, props.user.jwt), props.setFlash)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
setExpanded(false);
|
if(result !== undefined) {
|
||||||
setGameName("");
|
setExpanded(false);
|
||||||
setDate(null);
|
setGameName("");
|
||||||
|
setDate(null);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then(() => props.refetchGamenights())
|
.then(() => props.refetchGamenights());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {useState, useEffect} from 'react';
|
import {useState, useEffect, useCallback} from 'react';
|
||||||
import Checkbox from '@mui/material/Checkbox';
|
import Checkbox from '@mui/material/Checkbox';
|
||||||
import Table from '@mui/material/Table';
|
import Table from '@mui/material/Table';
|
||||||
import TableBody from '@mui/material/TableBody';
|
import TableBody from '@mui/material/TableBody';
|
||||||
@ -35,17 +35,25 @@ function AdminPanel(props) {
|
|||||||
setPage(0);
|
setPage(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
const refetchTokens = () => {
|
const refetchTokens = useCallback(() => {
|
||||||
if(props.user !== null) {
|
if(props.user !== null) {
|
||||||
unpack_api_result(get_registration_tokens(props.user.jwt), props.setFlash)
|
unpack_api_result(get_registration_tokens(props.user.jwt), props.setFlash)
|
||||||
.then(result => setRegistrationTokens(result.registration_tokens));
|
.then(result => {
|
||||||
}
|
if(result !== undefined) {
|
||||||
}
|
setRegistrationTokens(result.registration_tokens);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [props.setFlash, props.user]);
|
||||||
|
|
||||||
const deleteToken = (id) => {
|
const deleteToken = (id) => {
|
||||||
if(props.user !== null) {
|
if(props.user !== null) {
|
||||||
unpack_api_result(delete_registration_token(props.user.jwt, id), props.setFlash)
|
unpack_api_result(delete_registration_token(props.user.jwt, id), props.setFlash)
|
||||||
.then(() => refetchTokens())
|
.then(result => {
|
||||||
|
if(result !== undefined) {
|
||||||
|
refetchTokens();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,13 +65,17 @@ function AdminPanel(props) {
|
|||||||
|
|
||||||
if(props.user !== null) {
|
if(props.user !== null) {
|
||||||
unpack_api_result(add_registration_token(props.user.jwt, input), props.setFlash)
|
unpack_api_result(add_registration_token(props.user.jwt, input), props.setFlash)
|
||||||
.then(() => refetchTokens())
|
.then(result => {
|
||||||
|
if(result !== undefined) {
|
||||||
|
refetchTokens();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
refetchTokens()
|
refetchTokens()
|
||||||
}, [])
|
}, [refetchTokens])
|
||||||
|
|
||||||
let columns = [
|
let columns = [
|
||||||
{
|
{
|
||||||
@ -92,7 +104,7 @@ function AdminPanel(props) {
|
|||||||
<div className="Add-GameNight">
|
<div className="Add-GameNight">
|
||||||
<form autoComplete="off" onSubmit={e => { e.preventDefault(); }}>
|
<form autoComplete="off" onSubmit={e => { e.preventDefault(); }}>
|
||||||
<DateTimePicker
|
<DateTimePicker
|
||||||
label="Gamenight date and time"
|
label="Token expires at"
|
||||||
variant="standard"
|
variant="standard"
|
||||||
value={expires}
|
value={expires}
|
||||||
onChange={setExpires}
|
onChange={setExpires}
|
||||||
@ -153,8 +165,8 @@ function AdminPanel(props) {
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
deleteToken(row.id)
|
deleteToken(row.id)
|
||||||
}}>
|
}}>
|
||||||
<DeleteIcon />
|
<DeleteIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import List from '@mui/material/List';
|
import List from '@mui/material/List';
|
||||||
import ListItem from '@mui/material/ListItem';
|
import ListItem from '@mui/material/ListItem';
|
||||||
import ListItemText from '@mui/material/ListItemText';
|
import ListItemText from '@mui/material/ListItemText';
|
||||||
@ -13,17 +13,21 @@ import {unpack_api_result, get_gamenight, patch_gamenight} from '../api/Api';
|
|||||||
|
|
||||||
function Gamenight(props) {
|
function Gamenight(props) {
|
||||||
|
|
||||||
const [dense, setDense] = useState(true);
|
const dense = true;
|
||||||
const [gamenight, setGamenight] = useState(null);
|
const [gamenight, setGamenight] = useState(null);
|
||||||
|
|
||||||
const fetchGamenight = () => {
|
const fetchGamenight = useCallback(() => {
|
||||||
if (props.user !== null) {
|
if (props.user !== null) {
|
||||||
unpack_api_result(get_gamenight(props.gamenightId, props.user.jwt), props.setFlash)
|
unpack_api_result(get_gamenight(props.gamenightId, props.user.jwt), props.setFlash)
|
||||||
.then(result => setGamenight(result.gamenight));
|
.then(result => {
|
||||||
|
if(result !== undefined) {
|
||||||
|
setGamenight(result.gamenight);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}, [props.gamenightId, props.user, props.setFlash]);
|
||||||
|
|
||||||
useEffect(fetchGamenight, []);
|
useEffect(fetchGamenight, [fetchGamenight]);
|
||||||
|
|
||||||
let games = gamenight?.game_list.map(g =>
|
let games = gamenight?.game_list.map(g =>
|
||||||
(
|
(
|
||||||
@ -51,7 +55,11 @@ function Gamenight(props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
unpack_api_result(patch_gamenight(gamenight.id, input, props.user.jwt), props.setFlash)
|
unpack_api_result(patch_gamenight(gamenight.id, input, props.user.jwt), props.setFlash)
|
||||||
.then(() => fetchGamenight());
|
.then(result => {
|
||||||
|
if(result !== undefined) {
|
||||||
|
fetchGamenight();
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const Leave = () => {
|
const Leave = () => {
|
||||||
@ -60,7 +68,11 @@ function Gamenight(props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
unpack_api_result(patch_gamenight(gamenight.id, input, props.user.jwt), props.setFlash)
|
unpack_api_result(patch_gamenight(gamenight.id, input, props.user.jwt), props.setFlash)
|
||||||
.then(() => fetchGamenight());
|
.then(result => {
|
||||||
|
if(result !== undefined) {
|
||||||
|
fetchGamenight();
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let join_or_leave_button;
|
let join_or_leave_button;
|
||||||
|
@ -12,13 +12,18 @@ import AddGameNight from './AddGameNight';
|
|||||||
import {delete_gamenight, unpack_api_result} from '../api/Api';
|
import {delete_gamenight, unpack_api_result} from '../api/Api';
|
||||||
|
|
||||||
function Gamenights(props) {
|
function Gamenights(props) {
|
||||||
const [dense, setDense] = React.useState(false);
|
const dense = true;
|
||||||
|
|
||||||
const DeleteGamenight = (game_id) => {
|
const DeleteGamenight = (game_id) => {
|
||||||
if (props.user !== null) {
|
if (props.user !== null) {
|
||||||
const input = { game_id: game_id };
|
const input = { game_id: game_id };
|
||||||
unpack_api_result(delete_gamenight(input, props.user.jwt), props.setFlash)
|
unpack_api_result(delete_gamenight(input, props.user.jwt), props.setFlash)
|
||||||
.then(() => props.refetchGamenights());
|
.then(result => {
|
||||||
|
if(result !== undefined) {
|
||||||
|
console.log("hello?");
|
||||||
|
props.refetchGamenights();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,19 +8,13 @@ import MenuIcon from '@mui/icons-material/Menu';
|
|||||||
|
|
||||||
function MenuBar(props) {
|
function MenuBar(props) {
|
||||||
|
|
||||||
let adminPanelButton = null;
|
|
||||||
if (props.user?.role === 'Admin') {
|
|
||||||
adminPanelButton = (
|
|
||||||
<Button
|
|
||||||
color="inherit"
|
|
||||||
onClick={props.onAdmin}>
|
|
||||||
AdminPanel
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let userButton = null;
|
let userButton = null;
|
||||||
if (props.user != null) {
|
let logoutButton = null;
|
||||||
|
let adminPanelButton = null;
|
||||||
|
let registerButton = null;
|
||||||
|
if (props.user !== null) {
|
||||||
userButton = (
|
userButton = (
|
||||||
<Button
|
<Button
|
||||||
color="inherit"
|
color="inherit"
|
||||||
@ -28,6 +22,30 @@ function MenuBar(props) {
|
|||||||
{props.user.username}
|
{props.user.username}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
logoutButton = (
|
||||||
|
<Button
|
||||||
|
color="inherit"
|
||||||
|
onClick={props.onLogout}>
|
||||||
|
Logout
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
if (props.user.role === 'Admin') {
|
||||||
|
adminPanelButton = (
|
||||||
|
<Button
|
||||||
|
color="inherit"
|
||||||
|
onClick={props.onAdmin}>
|
||||||
|
AdminPanel
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
registerButton = (
|
||||||
|
<Button
|
||||||
|
color="inherit"
|
||||||
|
onClick={props.onRegister}>
|
||||||
|
Register
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -50,12 +68,9 @@ function MenuBar(props) {
|
|||||||
Gamenight!
|
Gamenight!
|
||||||
</Typography>
|
</Typography>
|
||||||
{userButton !== null && userButton}
|
{userButton !== null && userButton}
|
||||||
|
{registerButton !== null && registerButton}
|
||||||
{adminPanelButton !== null && adminPanelButton}
|
{adminPanelButton !== null && adminPanelButton}
|
||||||
<Button
|
{logoutButton !== null && logoutButton}
|
||||||
color="inherit"
|
|
||||||
onClick={props.onLogout}>
|
|
||||||
Logout
|
|
||||||
</Button>
|
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
);
|
);
|
||||||
|
98
frontend/src/components/Register.jsx
Normal file
98
frontend/src/components/Register.jsx
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import {useState} from 'react';
|
||||||
|
import FormControl from '@mui/material/FormControl';
|
||||||
|
import Input from '@mui/material/Input';
|
||||||
|
import FormHelperText from '@mui/material/FormHelperText';
|
||||||
|
import Button from '@mui/material/Button';
|
||||||
|
|
||||||
|
import {register, unpack_api_result} from '../api/Api';
|
||||||
|
|
||||||
|
function Register(props) {
|
||||||
|
const [registrationToken, setRegistrationToken] = useState("");
|
||||||
|
const [username, setUsername] = useState("");
|
||||||
|
const [email, setEmail] = useState("");
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
const [passwordRepeat, setPasswordRepeat] = useState("");
|
||||||
|
|
||||||
|
const onRegister = () => {
|
||||||
|
let input = {
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
password_repeat: passwordRepeat
|
||||||
|
}
|
||||||
|
|
||||||
|
unpack_api_result(register(registrationToken, input), props.setFlash)
|
||||||
|
.then(result => {
|
||||||
|
if(result !== undefined) {
|
||||||
|
props.onRegistered(result.user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
id="registration_token"
|
||||||
|
aria-describedby="registration_token-helper-text"
|
||||||
|
value={registrationToken}
|
||||||
|
onChange={(e) => {setRegistrationToken(e.target.value)}} />
|
||||||
|
<FormHelperText
|
||||||
|
id="registration_token-helper-text">
|
||||||
|
Registration token given by a gamenight admin
|
||||||
|
</FormHelperText>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
id="username"
|
||||||
|
aria-describedby="email-helper-text"
|
||||||
|
value={username}
|
||||||
|
onChange={(e) => {setUsername(e.target.value)}} />
|
||||||
|
<FormHelperText
|
||||||
|
id="username-helper-text">
|
||||||
|
Username to display everywhere
|
||||||
|
</FormHelperText>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
id="email"
|
||||||
|
aria-describedby="email-helper-text"
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => {setEmail(e.target.value)}} />
|
||||||
|
<FormHelperText
|
||||||
|
id="email-helper-text">
|
||||||
|
E-mail used for notifications and password resets
|
||||||
|
</FormHelperText>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
id="password"
|
||||||
|
type="password"
|
||||||
|
aria-describedby="password-helper-text"
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => {setPassword(e.target.value)}} />
|
||||||
|
<FormHelperText
|
||||||
|
id="password-helper-text">
|
||||||
|
Password atleast 10 characters long
|
||||||
|
</FormHelperText>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
id="password_repeat"
|
||||||
|
type="password"
|
||||||
|
aria-describedby="password_repeat-helper-text"
|
||||||
|
value={passwordRepeat}
|
||||||
|
onChange={(e) => {setPasswordRepeat(e.target.value)}} />
|
||||||
|
<FormHelperText
|
||||||
|
id="password_repeat-helper-text">
|
||||||
|
Confirm your password
|
||||||
|
</FormHelperText>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="success"
|
||||||
|
onClick={onRegister}>
|
||||||
|
Register
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Register;
|
Loading…
Reference in New Issue
Block a user