Change the data types of the internal interfaces, and switch password expiration to an AccountState
This commit is contained in:
parent
d0ba8d921d
commit
e19d97663d
@ -13,6 +13,10 @@ use crate::{
|
|||||||
asset_db::{self, AssetId, Assets},
|
asset_db::{self, AssetId, Assets},
|
||||||
database::{CharacterId, Database, GameId, SessionId, UserId},
|
database::{CharacterId, Database, GameId, SessionId, UserId},
|
||||||
types::{AppError, FatalError, GameOverview, Message, Rgb, Tabletop, User, UserOverview},
|
types::{AppError, FatalError, GameOverview, Message, Rgb, Tabletop, User, UserOverview},
|
||||||
|
types::{
|
||||||
|
AccountState, AppError, FatalError, GameOverview, Message, Rgb, Tabletop, User,
|
||||||
|
UserOverview,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_BACKGROUND_COLOR: Rgb = Rgb {
|
const DEFAULT_BACKGROUND_COLOR: Rgb = Rgb {
|
||||||
@ -171,7 +175,7 @@ impl Core {
|
|||||||
Some(_) => error(AppError::UsernameUnavailable),
|
Some(_) => error(AppError::UsernameUnavailable),
|
||||||
None => match state
|
None => match state
|
||||||
.db
|
.db
|
||||||
.save_user(None, username, "", false, true, Utc::now())
|
.create_user(username, "", false, AccountState::PasswordReset(Utc::now()))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(user_id) => ok(user_id),
|
Ok(user_id) => ok(user_id),
|
||||||
@ -180,7 +184,7 @@ impl Core {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn disable_user(&self, userid: UserId) -> ResultExt<(), AppError, FatalError> {
|
pub async fn disable_user(&self, _userid: UserId) -> ResultExt<(), AppError, FatalError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +192,14 @@ impl Core {
|
|||||||
let games = self.0.read().await.db.games().await;
|
let games = self.0.read().await.db.games().await;
|
||||||
match games {
|
match games {
|
||||||
// Ok(games) => ok(games.into_iter().map(|g| Game::from(g)).collect()),
|
// Ok(games) => ok(games.into_iter().map(|g| Game::from(g)).collect()),
|
||||||
Ok(games) => ok(games.into_iter().map(GameOverview::from).collect()),
|
Ok(games) => ok(games.into_iter().map(|game|
|
||||||
|
GameOverview{
|
||||||
|
id: game.id,
|
||||||
|
game_type: "".to_owned(),
|
||||||
|
game_name: game.name,
|
||||||
|
gm: game.gm,
|
||||||
|
players: game.players,
|
||||||
|
}).collect::<Vec<GameOverview>>()),
|
||||||
Err(err) => fatal(err),
|
Err(err) => fatal(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,7 +211,7 @@ impl Core {
|
|||||||
game_name: &str,
|
game_name: &str,
|
||||||
) -> ResultExt<GameId, AppError, FatalError> {
|
) -> ResultExt<GameId, AppError, FatalError> {
|
||||||
let state = self.0.read().await;
|
let state = self.0.read().await;
|
||||||
match state.db.save_game(None, gm, game_type, game_name).await {
|
match state.db.create_game(gm, game_type, game_name).await {
|
||||||
Ok(game_id) => ok(game_id),
|
Ok(game_id) => ok(game_id),
|
||||||
Err(err) => fatal(err),
|
Err(err) => fatal(err),
|
||||||
}
|
}
|
||||||
@ -283,16 +294,22 @@ impl Core {
|
|||||||
|
|
||||||
pub async fn save_user(
|
pub async fn save_user(
|
||||||
&self,
|
&self,
|
||||||
uuid: Option<UserId>,
|
id: UserId,
|
||||||
username: &str,
|
name: &str,
|
||||||
password: &str,
|
password: &str,
|
||||||
admin: bool,
|
admin: bool,
|
||||||
enabled: bool,
|
account_state: AccountState,
|
||||||
) -> ResultExt<UserId, AppError, FatalError> {
|
) -> ResultExt<UserId, AppError, FatalError> {
|
||||||
let state = self.0.read().await;
|
let state = self.0.read().await;
|
||||||
match state
|
match state
|
||||||
.db
|
.db
|
||||||
.save_user(uuid, username, password, admin, enabled, Utc::now())
|
.save_user(User {
|
||||||
|
id,
|
||||||
|
name: name.to_owned(),
|
||||||
|
password: password.to_owned(),
|
||||||
|
admin,
|
||||||
|
state: account_state,
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(uuid) => ok(uuid),
|
Ok(uuid) => ok(uuid),
|
||||||
@ -313,14 +330,7 @@ impl Core {
|
|||||||
};
|
};
|
||||||
match state
|
match state
|
||||||
.db
|
.db
|
||||||
.save_user(
|
.save_user(User{ password, state: AccountState::Normal, ..user })
|
||||||
Some(uuid),
|
|
||||||
&user.name,
|
|
||||||
&password,
|
|
||||||
user.admin,
|
|
||||||
user.enabled,
|
|
||||||
Utc::now(),
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(_) => ok(()),
|
Ok(_) => ok(()),
|
||||||
@ -330,9 +340,10 @@ impl Core {
|
|||||||
|
|
||||||
pub async fn auth(
|
pub async fn auth(
|
||||||
&self,
|
&self,
|
||||||
username: &str,
|
_username: &str,
|
||||||
password: &str,
|
_password: &str,
|
||||||
) -> ResultExt<AuthResponse, AppError, FatalError> {
|
) -> ResultExt<AuthResponse, AppError, FatalError> {
|
||||||
|
/*
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
let state = self.0.read().await;
|
let state = self.0.read().await;
|
||||||
match state.db.user_by_username(username).await {
|
match state.db.user_by_username(username).await {
|
||||||
@ -355,6 +366,8 @@ impl Core {
|
|||||||
Ok(_) => error(AppError::AuthFailed),
|
Ok(_) => error(AppError::AuthFailed),
|
||||||
Err(err) => fatal(err),
|
Err(err) => fatal(err),
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn session(
|
pub async fn session(
|
||||||
@ -414,17 +427,20 @@ mod test {
|
|||||||
]);
|
]);
|
||||||
let memory_db: Option<PathBuf> = None;
|
let memory_db: Option<PathBuf> = None;
|
||||||
let conn = DbConn::new(memory_db);
|
let conn = DbConn::new(memory_db);
|
||||||
conn.save_user(
|
conn.create_user(
|
||||||
Some(UserId::from("admin")),
|
|
||||||
"admin",
|
"admin",
|
||||||
"aoeu",
|
"aoeu",
|
||||||
true,
|
true,
|
||||||
true,
|
AccountState::PasswordReset(Utc::now()),
|
||||||
Utc::now(),
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
conn.save_user(None, "gm_1", "aoeu", false, true, Utc::now())
|
conn.create_user(
|
||||||
|
"gm_1",
|
||||||
|
"aoeu",
|
||||||
|
false,
|
||||||
|
AccountState::PasswordReset(Utc::now()),
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Core::new(assets, conn)
|
Core::new(assets, conn)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use async_std::channel::Receiver;
|
use async_std::channel::Receiver;
|
||||||
use chrono::Utc;
|
|
||||||
use include_dir::{include_dir, Dir};
|
use include_dir::{include_dir, Dir};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
@ -9,13 +8,10 @@ use rusqlite_migration::Migrations;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
database::{DatabaseResponse, Request},
|
database::{DatabaseResponse, Request},
|
||||||
types::FatalError,
|
types::{AccountState, FatalError, Game, User},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{types::GameId, CharacterId, CharsheetRow, DatabaseRequest, SessionId, UserId};
|
||||||
types::{DateTime, GameId},
|
|
||||||
CharacterId, CharsheetRow, DatabaseRequest, GameRow, SessionId, UserId, UserRow,
|
|
||||||
};
|
|
||||||
|
|
||||||
static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/migrations");
|
static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/migrations");
|
||||||
|
|
||||||
@ -47,24 +43,23 @@ impl DiskDb {
|
|||||||
Ok(DiskDb { conn })
|
Ok(DiskDb { conn })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user(&self, id: &UserId) -> Result<Option<UserRow>, FatalError> {
|
pub fn user(&self, id: &UserId) -> Result<Option<User>, FatalError> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.conn
|
.conn
|
||||||
.prepare("SELECT * FROM users WHERE uuid=?")
|
.prepare("SELECT * FROM users WHERE uuid=?")
|
||||||
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
||||||
let items: Vec<UserRow> = stmt
|
let items: Vec<User> = stmt
|
||||||
.query_map([id.as_str()], |row| {
|
.query_map([id.as_str()], |row| {
|
||||||
Ok(UserRow {
|
Ok(User {
|
||||||
id: row.get(0).unwrap(),
|
id: row.get(0).unwrap(),
|
||||||
name: row.get(1).unwrap(),
|
name: row.get(1).unwrap(),
|
||||||
password: row.get(2).unwrap(),
|
password: row.get(2).unwrap(),
|
||||||
admin: row.get(3).unwrap(),
|
admin: row.get(3).unwrap(),
|
||||||
enabled: row.get(4).unwrap(),
|
state: row.get(4).unwrap(),
|
||||||
password_expires: row.get(5).unwrap(),
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.collect::<Result<Vec<UserRow>, rusqlite::Error>>()
|
.collect::<Result<Vec<User>, rusqlite::Error>>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
match &items[..] {
|
match &items[..] {
|
||||||
[] => Ok(None),
|
[] => Ok(None),
|
||||||
@ -73,24 +68,23 @@ impl DiskDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_by_username(&self, username: &str) -> Result<Option<UserRow>, FatalError> {
|
pub fn user_by_username(&self, username: &str) -> Result<Option<User>, FatalError> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.conn
|
.conn
|
||||||
.prepare("SELECT * FROM users WHERE name=?")
|
.prepare("SELECT * FROM users WHERE name=?")
|
||||||
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
||||||
let items: Vec<UserRow> = stmt
|
let items: Vec<User> = stmt
|
||||||
.query_map([username], |row| {
|
.query_map([username], |row| {
|
||||||
Ok(UserRow {
|
Ok(User {
|
||||||
id: row.get(0).unwrap(),
|
id: row.get(0).unwrap(),
|
||||||
name: row.get(1).unwrap(),
|
name: row.get(1).unwrap(),
|
||||||
password: row.get(2).unwrap(),
|
password: row.get(2).unwrap(),
|
||||||
admin: row.get(3).unwrap(),
|
admin: row.get(3).unwrap(),
|
||||||
enabled: row.get(4).unwrap(),
|
state: row.get(4).unwrap(),
|
||||||
password_expires: row.get(5).unwrap(),
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.collect::<Result<Vec<UserRow>, rusqlite::Error>>()
|
.collect::<Result<Vec<User>, rusqlite::Error>>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
match &items[..] {
|
match &items[..] {
|
||||||
[] => Ok(None),
|
[] => Ok(None),
|
||||||
@ -99,81 +93,72 @@ impl DiskDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_user(
|
pub fn create_user(
|
||||||
&self,
|
&self,
|
||||||
user_id: Option<UserId>,
|
|
||||||
name: &str,
|
name: &str,
|
||||||
password: &str,
|
password: &str,
|
||||||
admin: bool,
|
admin: bool,
|
||||||
enabled: bool,
|
state: AccountState,
|
||||||
expiration: chrono::DateTime<Utc>,
|
|
||||||
) -> Result<UserId, FatalError> {
|
) -> Result<UserId, FatalError> {
|
||||||
match user_id {
|
|
||||||
None => {
|
|
||||||
let user_id = UserId::default();
|
let user_id = UserId::default();
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.conn
|
.conn
|
||||||
.prepare("INSERT INTO users VALUES (?, ?, ?, ?, ?, ?)")
|
.prepare("INSERT INTO users VALUES (?, ?, ?, ?, ?)")
|
||||||
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
||||||
stmt.execute((
|
stmt.execute((user_id.as_str(), name, password, admin, state))
|
||||||
user_id.as_str(),
|
|
||||||
name,
|
|
||||||
password,
|
|
||||||
admin,
|
|
||||||
enabled,
|
|
||||||
format!("{}", expiration.format("%Y-%m-%d %H:%M:%S")),
|
|
||||||
))
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Ok(user_id)
|
Ok(user_id)
|
||||||
}
|
}
|
||||||
Some(user_id) => {
|
|
||||||
let mut stmt = self
|
|
||||||
.conn
|
|
||||||
.prepare("UPDATE users SET name=?, password=?, admin=?, enabled=?, password_expires=? WHERE uuid=?")
|
|
||||||
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
|
||||||
stmt.execute((
|
|
||||||
name,
|
|
||||||
password,
|
|
||||||
admin,
|
|
||||||
enabled,
|
|
||||||
format!("{}", expiration.format("%Y-%m-%d %H:%M:%S")),
|
|
||||||
user_id.as_str(),
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
Ok(user_id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn users(&self) -> Result<Vec<UserRow>, FatalError> {
|
pub fn save_user(&self, user: User) -> Result<UserId, FatalError> {
|
||||||
|
let mut stmt = self
|
||||||
|
.conn
|
||||||
|
.prepare("UPDATE users SET name=?, password=?, admin=?, state=? WHERE uuid=?")
|
||||||
|
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
||||||
|
stmt.execute((
|
||||||
|
user.name,
|
||||||
|
user.password,
|
||||||
|
user.admin,
|
||||||
|
user.state,
|
||||||
|
// format!("{}", expiration.format("%Y-%m-%d %H:%M:%S")),
|
||||||
|
user.id.as_str(),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
Ok(user.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn users(&self) -> Result<Vec<User>, FatalError> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.conn
|
.conn
|
||||||
.prepare("SELECT * FROM users")
|
.prepare("SELECT * FROM users")
|
||||||
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
||||||
let items = stmt
|
let items = stmt
|
||||||
.query_map([], |row| {
|
.query_map([], |row| {
|
||||||
Ok(UserRow {
|
Ok(User {
|
||||||
id: row.get(0).unwrap(),
|
id: row.get(0).unwrap(),
|
||||||
name: row.get(1).unwrap(),
|
name: row.get(1).unwrap(),
|
||||||
password: row.get(2).unwrap(),
|
password: row.get(2).unwrap(),
|
||||||
admin: row.get(3).unwrap(),
|
admin: row.get(3).unwrap(),
|
||||||
enabled: row.get(4).unwrap(),
|
state: row.get(4).unwrap(),
|
||||||
password_expires: row.get(5).unwrap(),
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.collect::<Result<Vec<UserRow>, rusqlite::Error>>()
|
.collect::<Result<Vec<User>, rusqlite::Error>>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Ok(items)
|
Ok(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_game(
|
pub fn create_game(
|
||||||
&self,
|
&self,
|
||||||
game_id: Option<GameId>,
|
_gm: &UserId,
|
||||||
gm: &UserId,
|
_game_type: &str,
|
||||||
game_type: &str,
|
_name: &str,
|
||||||
name: &str,
|
|
||||||
) -> Result<GameId, FatalError> {
|
) -> Result<GameId, FatalError> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save_game(&self, _game: Game) -> Result<(), FatalError> {
|
||||||
|
/*
|
||||||
match game_id {
|
match game_id {
|
||||||
None => {
|
None => {
|
||||||
let game_id = GameId::new();
|
let game_id = GameId::new();
|
||||||
@ -195,46 +180,47 @@ impl DiskDb {
|
|||||||
Ok(game_id)
|
Ok(game_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn games(&self) -> Result<Vec<GameRow>, FatalError> {
|
pub fn games(&self) -> Result<Vec<Game>, FatalError> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.conn
|
.conn
|
||||||
.prepare("SELECT * FROM games")
|
.prepare("SELECT * FROM games")
|
||||||
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
||||||
let items = stmt
|
let items = stmt
|
||||||
.query_map([], |row| {
|
.query_map([], |row| {
|
||||||
Ok(GameRow {
|
Ok(Game {
|
||||||
id: row.get(0).unwrap(),
|
id: row.get(0).unwrap(),
|
||||||
gm: row.get(1).unwrap(),
|
gm: row.get(1).unwrap(),
|
||||||
game_type: row.get(2).unwrap(),
|
|
||||||
name: row.get(3).unwrap(),
|
name: row.get(3).unwrap(),
|
||||||
|
players: vec![],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.collect::<Result<Vec<GameRow>, rusqlite::Error>>()
|
.collect::<Result<Vec<Game>, rusqlite::Error>>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Ok(items)
|
Ok(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session(&self, session_id: &SessionId) -> Result<Option<UserRow>, FatalError> {
|
pub fn session(&self, session_id: &SessionId) -> Result<Option<User>, FatalError> {
|
||||||
let mut stmt = self.conn
|
let mut stmt = self.conn
|
||||||
.prepare("SELECT u.uuid, u.name, u.password, u.admin, u.enabled FROM sessions s INNER JOIN users u ON u.uuid = s.user_id WHERE s.id = ?")
|
.prepare("SELECT u.uuid, u.name, u.password, u.admin, u.enabled FROM sessions s INNER JOIN users u ON u.uuid = s.user_id WHERE s.id = ?")
|
||||||
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
.map_err(|err| FatalError::ConstructQueryFailure(format!("{}", err)))?;
|
||||||
|
|
||||||
let items: Vec<UserRow> = stmt
|
let items: Vec<User> = stmt
|
||||||
.query_map([session_id.as_str()], |row| {
|
.query_map([session_id.as_str()], |row| {
|
||||||
Ok(UserRow {
|
Ok(User {
|
||||||
id: row.get(0).unwrap(),
|
id: row.get(0).unwrap(),
|
||||||
name: row.get(1).unwrap(),
|
name: row.get(1).unwrap(),
|
||||||
password: row.get(2).unwrap(),
|
password: row.get(2).unwrap(),
|
||||||
admin: row.get(3).unwrap(),
|
admin: row.get(3).unwrap(),
|
||||||
enabled: row.get(4).unwrap(),
|
state: row.get(4).unwrap(),
|
||||||
password_expires: row.get(5).unwrap(),
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.collect::<Result<Vec<UserRow>, rusqlite::Error>>()
|
.collect::<Result<Vec<User>, rusqlite::Error>>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
match &items[..] {
|
match &items[..] {
|
||||||
[] => Ok(None),
|
[] => Ok(None),
|
||||||
@ -331,6 +317,8 @@ pub async fn db_handler(db: DiskDb, requestor: Receiver<DatabaseRequest>) {
|
|||||||
_ => unimplemented!("errors for Charsheet"),
|
_ => unimplemented!("errors for Charsheet"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Request::CreateUser(_, _, _, _) => {}
|
||||||
|
Request::CreateGame(_, _, _) => {}
|
||||||
Request::CreateSession(id) => {
|
Request::CreateSession(id) => {
|
||||||
let session_id = db.create_session(&id).unwrap();
|
let session_id = db.create_session(&id).unwrap();
|
||||||
tx.send(DatabaseResponse::CreateSession(session_id))
|
tx.send(DatabaseResponse::CreateSession(session_id))
|
||||||
@ -344,11 +332,12 @@ pub async fn db_handler(db: DiskDb, requestor: Receiver<DatabaseRequest>) {
|
|||||||
Request::Game(_game_id) => {
|
Request::Game(_game_id) => {
|
||||||
unimplemented!("Request::Game handler");
|
unimplemented!("Request::Game handler");
|
||||||
}
|
}
|
||||||
Request::SaveGame(game_id, user_id, game_type, game_name) => {
|
Request::SaveGame(game) => {
|
||||||
let game_id = db.save_game(game_id, &user_id, &game_type, &game_name);
|
let id = game.id.clone();
|
||||||
match game_id {
|
let save_result = db.save_game(game);
|
||||||
Ok(game_id) => {
|
match save_result {
|
||||||
tx.send(DatabaseResponse::SaveGame(game_id)).await.unwrap();
|
Ok(_) => {
|
||||||
|
tx.send(DatabaseResponse::SaveGame(id)).await.unwrap();
|
||||||
}
|
}
|
||||||
err => panic!("{:?}", err),
|
err => panic!("{:?}", err),
|
||||||
}
|
}
|
||||||
@ -369,15 +358,8 @@ pub async fn db_handler(db: DiskDb, requestor: Receiver<DatabaseRequest>) {
|
|||||||
err => panic!("{:?}", err),
|
err => panic!("{:?}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Request::SaveUser(user_id, username, password, admin, enabled, expiration) => {
|
Request::SaveUser(user) => {
|
||||||
let user_id = db.save_user(
|
let user_id = db.save_user(user);
|
||||||
user_id,
|
|
||||||
username.as_ref(),
|
|
||||||
password.as_ref(),
|
|
||||||
admin,
|
|
||||||
enabled,
|
|
||||||
expiration,
|
|
||||||
);
|
|
||||||
match user_id {
|
match user_id {
|
||||||
Ok(user_id) => {
|
Ok(user_id) => {
|
||||||
tx.send(DatabaseResponse::SaveUser(user_id)).await.unwrap();
|
tx.send(DatabaseResponse::SaveUser(user_id)).await.unwrap();
|
||||||
|
@ -5,20 +5,21 @@ use std::path::Path;
|
|||||||
|
|
||||||
use async_std::channel::{bounded, Sender};
|
use async_std::channel::{bounded, Sender};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use chrono::{DateTime, Utc};
|
|
||||||
use disk_db::{db_handler, DiskDb};
|
use disk_db::{db_handler, DiskDb};
|
||||||
pub use types::{CharacterId, CharsheetRow, GameId, GameRow, SessionId, UserId, UserRow};
|
pub use types::{CharacterId, CharsheetRow, GameId, SessionId, UserId};
|
||||||
|
|
||||||
use crate::types::FatalError;
|
use crate::types::{AccountState, FatalError, Game, User};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Request {
|
enum Request {
|
||||||
Charsheet(CharacterId),
|
Charsheet(CharacterId),
|
||||||
|
CreateGame(UserId, String, String),
|
||||||
CreateSession(UserId),
|
CreateSession(UserId),
|
||||||
Games,
|
CreateUser(String, String, bool, AccountState),
|
||||||
Game(GameId),
|
Game(GameId),
|
||||||
SaveGame(Option<GameId>, UserId, String, String),
|
Games,
|
||||||
SaveUser(Option<UserId>, String, String, bool, bool, DateTime<Utc>),
|
SaveGame(Game),
|
||||||
|
SaveUser(User),
|
||||||
Session(SessionId),
|
Session(SessionId),
|
||||||
User(UserId),
|
User(UserId),
|
||||||
UserByUsername(String),
|
UserByUsername(String),
|
||||||
@ -35,50 +36,43 @@ struct DatabaseRequest {
|
|||||||
enum DatabaseResponse {
|
enum DatabaseResponse {
|
||||||
Charsheet(Option<CharsheetRow>),
|
Charsheet(Option<CharsheetRow>),
|
||||||
CreateSession(SessionId),
|
CreateSession(SessionId),
|
||||||
Games(Vec<GameRow>),
|
Games(Vec<Game>),
|
||||||
Game(Option<GameRow>),
|
Game(Option<Game>),
|
||||||
SaveGame(GameId),
|
SaveGame(GameId),
|
||||||
SaveUser(UserId),
|
SaveUser(UserId),
|
||||||
Session(Option<UserRow>),
|
Session(Option<User>),
|
||||||
User(Option<UserRow>),
|
User(Option<User>),
|
||||||
Users(Vec<UserRow>),
|
Users(Vec<User>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Database: Send + Sync {
|
pub trait Database: Send + Sync {
|
||||||
async fn users(&self) -> Result<Vec<UserRow>, FatalError>;
|
async fn create_session(&self, id: &UserId) -> Result<SessionId, FatalError>;
|
||||||
|
async fn session(&self, id: &SessionId) -> Result<Option<User>, FatalError>;
|
||||||
async fn user(&self, _: &UserId) -> Result<Option<UserRow>, FatalError>;
|
|
||||||
|
|
||||||
async fn user_by_username(&self, _: &str) -> Result<Option<UserRow>, FatalError>;
|
|
||||||
|
|
||||||
async fn save_user(
|
|
||||||
&self,
|
|
||||||
user_id: Option<UserId>,
|
|
||||||
name: &str,
|
|
||||||
password: &str,
|
|
||||||
admin: bool,
|
|
||||||
enabled: bool,
|
|
||||||
expiration: DateTime<Utc>,
|
|
||||||
) -> Result<UserId, FatalError>;
|
|
||||||
|
|
||||||
async fn games(&self) -> Result<Vec<GameRow>, FatalError>;
|
|
||||||
|
|
||||||
async fn game(&self, _: &GameId) -> Result<Option<GameRow>, FatalError>;
|
|
||||||
|
|
||||||
async fn save_game(
|
|
||||||
&self,
|
|
||||||
game_id: Option<GameId>,
|
|
||||||
gm: &UserId,
|
|
||||||
game_type: &str,
|
|
||||||
game_name: &str,
|
|
||||||
) -> Result<GameId, FatalError>;
|
|
||||||
|
|
||||||
async fn character(&self, id: &CharacterId) -> Result<Option<CharsheetRow>, FatalError>;
|
async fn character(&self, id: &CharacterId) -> Result<Option<CharsheetRow>, FatalError>;
|
||||||
|
|
||||||
async fn session(&self, id: &SessionId) -> Result<Option<UserRow>, FatalError>;
|
async fn create_game(
|
||||||
|
&self,
|
||||||
|
gm: &UserId,
|
||||||
|
game_type: &str,
|
||||||
|
name: &str,
|
||||||
|
) -> Result<GameId, FatalError>;
|
||||||
|
async fn save_game(&self, game: Game) -> Result<GameId, FatalError>;
|
||||||
|
async fn game(&self, _: &GameId) -> Result<Option<Game>, FatalError>;
|
||||||
|
async fn games(&self) -> Result<Vec<Game>, FatalError>;
|
||||||
|
|
||||||
async fn create_session(&self, id: &UserId) -> Result<SessionId, FatalError>;
|
async fn create_user(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
password: &str,
|
||||||
|
admin: bool,
|
||||||
|
state: AccountState,
|
||||||
|
) -> Result<UserId, FatalError>;
|
||||||
|
async fn save_user(&self, user: User) -> Result<UserId, FatalError>;
|
||||||
|
async fn user(&self, _: &UserId) -> Result<Option<User>, FatalError>;
|
||||||
|
async fn user_by_username(&self, _: &str) -> Result<Option<User>, FatalError>;
|
||||||
|
async fn users(&self) -> Result<Vec<User>, FatalError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DbConn {
|
pub struct DbConn {
|
||||||
@ -125,67 +119,58 @@ macro_rules! send_request {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Database for DbConn {
|
impl Database for DbConn {
|
||||||
async fn users(&self) -> Result<Vec<UserRow>, FatalError> {
|
async fn create_session(&self, id: &UserId) -> Result<SessionId, FatalError> {
|
||||||
send_request!(self, Request::Users, DatabaseResponse::Users(lst) => Ok(lst))
|
send_request!(self, Request::CreateSession(id.to_owned()), DatabaseResponse::CreateSession(session_id) => Ok(session_id))
|
||||||
}
|
}
|
||||||
|
async fn session(&self, id: &SessionId) -> Result<Option<User>, FatalError> {
|
||||||
async fn user(&self, uid: &UserId) -> Result<Option<UserRow>, FatalError> {
|
send_request!(self, Request::Session(id.to_owned()), DatabaseResponse::Session(row) => Ok(row))
|
||||||
send_request!(self, Request::User(uid.clone()), DatabaseResponse::User(user) => Ok(user))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn user_by_username(&self, username: &str) -> Result<Option<UserRow>, FatalError> {
|
|
||||||
send_request!(self, Request::UserByUsername(username.to_owned()), DatabaseResponse::User(user) => Ok(user))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn save_user(
|
|
||||||
&self,
|
|
||||||
user_id: Option<UserId>,
|
|
||||||
name: &str,
|
|
||||||
password: &str,
|
|
||||||
admin: bool,
|
|
||||||
enabled: bool,
|
|
||||||
expiration: DateTime<Utc>,
|
|
||||||
) -> Result<UserId, FatalError> {
|
|
||||||
send_request!(self,
|
|
||||||
Request::SaveUser(
|
|
||||||
user_id,
|
|
||||||
name.to_owned(),
|
|
||||||
password.to_owned(),
|
|
||||||
admin,
|
|
||||||
enabled,
|
|
||||||
expiration,
|
|
||||||
),
|
|
||||||
DatabaseResponse::SaveUser(user_id) => Ok(user_id))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn games(&self) -> Result<Vec<GameRow>, FatalError> {
|
|
||||||
send_request!(self, Request::Games, DatabaseResponse::Games(lst) => Ok(lst))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn game(&self, game_id: &GameId) -> Result<Option<GameRow>, FatalError> {
|
|
||||||
send_request!(self, Request::Game(game_id.clone()), DatabaseResponse::Game(game) => Ok(game))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn save_game(
|
|
||||||
&self,
|
|
||||||
game_id: Option<GameId>,
|
|
||||||
user_id: &UserId,
|
|
||||||
game_type: &str,
|
|
||||||
game_name: &str,
|
|
||||||
) -> Result<GameId, FatalError> {
|
|
||||||
send_request!(self, Request::SaveGame(game_id, user_id.to_owned(), game_type.to_owned(), game_name.to_owned()), DatabaseResponse::SaveGame(game_id) => Ok(game_id))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn character(&self, id: &CharacterId) -> Result<Option<CharsheetRow>, FatalError> {
|
async fn character(&self, id: &CharacterId) -> Result<Option<CharsheetRow>, FatalError> {
|
||||||
send_request!(self, Request::Charsheet(id.to_owned()), DatabaseResponse::Charsheet(row) => Ok(row))
|
send_request!(self, Request::Charsheet(id.to_owned()), DatabaseResponse::Charsheet(row) => Ok(row))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn session(&self, id: &SessionId) -> Result<Option<UserRow>, FatalError> {
|
async fn create_game(
|
||||||
send_request!(self, Request::Session(id.to_owned()), DatabaseResponse::Session(row) => Ok(row))
|
&self,
|
||||||
|
user_id: &UserId,
|
||||||
|
game_type: &str,
|
||||||
|
game_name: &str,
|
||||||
|
) -> Result<GameId, FatalError> {
|
||||||
|
send_request!(self, Request::CreateGame(user_id.to_owned(), game_type.to_owned(), game_name.to_owned()), DatabaseResponse::SaveGame(game_id) => Ok(game_id))
|
||||||
|
}
|
||||||
|
async fn save_game(&self, game: Game) -> Result<GameId, FatalError> {
|
||||||
|
send_request!(self, Request::SaveGame(game), DatabaseResponse::SaveGame(game_id) => Ok(game_id))
|
||||||
|
}
|
||||||
|
async fn game(&self, game_id: &GameId) -> Result<Option<Game>, FatalError> {
|
||||||
|
send_request!(self, Request::Game(game_id.clone()), DatabaseResponse::Game(game) => Ok(game))
|
||||||
|
}
|
||||||
|
async fn games(&self) -> Result<Vec<Game>, FatalError> {
|
||||||
|
send_request!(self, Request::Games, DatabaseResponse::Games(lst) => Ok(lst))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_session(&self, id: &UserId) -> Result<SessionId, FatalError> {
|
async fn create_user(
|
||||||
send_request!(self, Request::CreateSession(id.to_owned()), DatabaseResponse::CreateSession(session_id) => Ok(session_id))
|
&self,
|
||||||
|
name: &str,
|
||||||
|
password: &str,
|
||||||
|
admin: bool,
|
||||||
|
state: AccountState,
|
||||||
|
) -> Result<UserId, FatalError> {
|
||||||
|
send_request!(self,
|
||||||
|
Request::CreateUser(name.to_owned(), password.to_owned(), admin, state),
|
||||||
|
DatabaseResponse::SaveUser(user_id) => Ok(user_id))
|
||||||
|
}
|
||||||
|
async fn save_user(&self, user: User) -> Result<UserId, FatalError> {
|
||||||
|
send_request!(self,
|
||||||
|
Request::SaveUser(user),
|
||||||
|
DatabaseResponse::SaveUser(user_id) => Ok(user_id))
|
||||||
|
}
|
||||||
|
async fn user(&self, uid: &UserId) -> Result<Option<User>, FatalError> {
|
||||||
|
send_request!(self, Request::User(uid.clone()), DatabaseResponse::User(user) => Ok(user))
|
||||||
|
}
|
||||||
|
async fn user_by_username(&self, username: &str) -> Result<Option<User>, FatalError> {
|
||||||
|
send_request!(self, Request::UserByUsername(username.to_owned()), DatabaseResponse::User(user) => Ok(user))
|
||||||
|
}
|
||||||
|
async fn users(&self) -> Result<Vec<User>, FatalError> {
|
||||||
|
send_request!(self, Request::Users, DatabaseResponse::Users(lst) => Ok(lst))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,11 +190,15 @@ mod test {
|
|||||||
let no_path: Option<PathBuf> = None;
|
let no_path: Option<PathBuf> = None;
|
||||||
let db = DiskDb::new(no_path).unwrap();
|
let db = DiskDb::new(no_path).unwrap();
|
||||||
|
|
||||||
let now = Utc::now();
|
db.create_user("admin", "abcdefg", true, AccountState::Normal)
|
||||||
|
.unwrap();
|
||||||
db.save_user(Some(UserId::from("admin")), "admin", "abcdefg", true, true, now)
|
let game_id = db
|
||||||
|
.create_game(
|
||||||
|
&UserId::from("admin"),
|
||||||
|
"Candela",
|
||||||
|
"Circle of the Winter Solstice",
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let game_id = db.save_game(None, &UserId::from("admin"), "Candela", "Circle of the Winter Solstice").unwrap();
|
|
||||||
(db, game_id)
|
(db, game_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,16 +160,6 @@ impl FromSql for CharacterId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct UserRow {
|
|
||||||
pub id: UserId,
|
|
||||||
pub name: String,
|
|
||||||
pub password: String,
|
|
||||||
pub admin: bool,
|
|
||||||
pub enabled: bool,
|
|
||||||
pub password_expires: DateTime,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Role {
|
pub struct Role {
|
||||||
userid: UserId,
|
userid: UserId,
|
||||||
@ -177,6 +167,7 @@ pub struct Role {
|
|||||||
role: String,
|
role: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct GameRow {
|
pub struct GameRow {
|
||||||
pub id: GameId,
|
pub id: GameId,
|
||||||
@ -184,6 +175,7 @@ pub struct GameRow {
|
|||||||
pub game_type: String,
|
pub game_type: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CharsheetRow {
|
pub struct CharsheetRow {
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
use axum::{
|
use axum::{http::HeaderMap, Json};
|
||||||
http::HeaderMap,
|
|
||||||
Json,
|
|
||||||
};
|
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use result_extended::{error, fatal, ok, return_error, ResultExt};
|
use result_extended::{error, ok, return_error, ResultExt};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use typeshare::typeshare;
|
use typeshare::typeshare;
|
||||||
|
|
||||||
@ -97,10 +94,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn check_password(
|
pub async fn check_password(
|
||||||
core: Core,
|
_core: Core,
|
||||||
req: Json<AuthRequest>,
|
req: Json<AuthRequest>,
|
||||||
) -> ResultExt<AuthResponse, AppError, FatalError> {
|
) -> ResultExt<AuthResponse, AppError, FatalError> {
|
||||||
let Json(AuthRequest { username, password }) = req;
|
let Json(AuthRequest {
|
||||||
|
username: _,
|
||||||
|
password: _,
|
||||||
|
}) = req;
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
/*
|
/*
|
||||||
match core.auth(&username, &password).await {
|
match core.auth(&username, &password).await {
|
||||||
@ -118,7 +118,8 @@ pub async fn get_user(
|
|||||||
Some(user_id) => core.user(user_id).await,
|
Some(user_id) => core.user(user_id).await,
|
||||||
None => core.user(user.id).await,
|
None => core.user(user.id).await,
|
||||||
}
|
}
|
||||||
}).await
|
})
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_users(
|
pub async fn get_users(
|
||||||
@ -127,7 +128,8 @@ pub async fn get_users(
|
|||||||
) -> ResultExt<Vec<UserOverview>, AppError, FatalError> {
|
) -> ResultExt<Vec<UserOverview>, AppError, FatalError> {
|
||||||
auth_required(core.clone(), headers, |_user| async move {
|
auth_required(core.clone(), headers, |_user| async move {
|
||||||
core.list_users().await
|
core.list_users().await
|
||||||
}).await
|
})
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_user(
|
pub async fn create_user(
|
||||||
@ -137,7 +139,8 @@ pub async fn create_user(
|
|||||||
) -> ResultExt<UserId, AppError, FatalError> {
|
) -> ResultExt<UserId, AppError, FatalError> {
|
||||||
admin_required(core.clone(), headers, |_admin| async {
|
admin_required(core.clone(), headers, |_admin| async {
|
||||||
core.create_user(&req.username).await
|
core.create_user(&req.username).await
|
||||||
}).await
|
})
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_password(
|
pub async fn set_password(
|
||||||
@ -151,5 +154,6 @@ pub async fn set_password(
|
|||||||
} else {
|
} else {
|
||||||
error(AppError::BadRequest)
|
error(AppError::BadRequest)
|
||||||
}
|
}
|
||||||
}).await
|
})
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ mod test {
|
|||||||
use crate::{
|
use crate::{
|
||||||
asset_db::FsAssets,
|
asset_db::FsAssets,
|
||||||
core::{AuthResponse, Core},
|
core::{AuthResponse, Core},
|
||||||
database::{Database, DbConn, GameId, SessionId, UserId},
|
database::{DbConn, GameId, SessionId, UserId},
|
||||||
handlers::CreateGameRequest,
|
handlers::CreateGameRequest,
|
||||||
types::UserOverview,
|
types::UserOverview,
|
||||||
};
|
};
|
||||||
@ -240,13 +240,13 @@ mod test {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn it_refuses_to_authenticate_a_disabled_user() {
|
async fn it_refuses_to_authenticate_a_disabled_user() {
|
||||||
let (_core, server) = setup_with_disabled_user().await;
|
let (_core, _server) = setup_with_disabled_user().await;
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn it_forces_changing_expired_password() {
|
async fn it_forces_changing_expired_password() {
|
||||||
let (_core, server) = setup_with_user().await;
|
let (_core, _server) = setup_with_user().await;
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
use rusqlite::{types::{FromSql, FromSqlError, ToSqlOutput, ValueRef}, ToSql};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@ -6,7 +7,7 @@ use typeshare::typeshare;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
asset_db::AssetId,
|
asset_db::AssetId,
|
||||||
database::{GameId, GameRow, UserId, UserRow},
|
database::{GameId, UserId},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@ -71,6 +72,43 @@ pub struct Rgb {
|
|||||||
pub blue: u32,
|
pub blue: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[typeshare]
|
||||||
|
pub enum AccountState {
|
||||||
|
Normal,
|
||||||
|
PasswordReset(DateTime<Utc>),
|
||||||
|
Locked,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromSql for AccountState {
|
||||||
|
fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
|
||||||
|
if let ValueRef::Text(text) = value {
|
||||||
|
let text = String::from_utf8(text.to_vec()).unwrap();
|
||||||
|
if text.starts_with("Normal") {
|
||||||
|
Ok(AccountState::Normal)
|
||||||
|
} else if text.starts_with("PasswordReset") {
|
||||||
|
unimplemented!()
|
||||||
|
} else if text.starts_with("Locked") {
|
||||||
|
Ok(AccountState::Locked)
|
||||||
|
} else {
|
||||||
|
Err(FromSqlError::InvalidType)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(FromSqlError::InvalidType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToSql for AccountState {
|
||||||
|
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
|
||||||
|
match self {
|
||||||
|
AccountState::Normal => Ok(ToSqlOutput::Borrowed(ValueRef::Text("Normal".as_bytes()))),
|
||||||
|
AccountState::PasswordReset(_expiration) => unimplemented!(),
|
||||||
|
AccountState::Locked => Ok(ToSqlOutput::Borrowed(ValueRef::Text("Locked".as_bytes()))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[typeshare]
|
#[typeshare]
|
||||||
@ -79,21 +117,7 @@ pub struct User {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
pub enabled: bool,
|
pub state: AccountState,
|
||||||
pub expiration: DateTime<Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<UserRow> for User {
|
|
||||||
fn from(row: UserRow) -> Self {
|
|
||||||
Self {
|
|
||||||
id: row.id,
|
|
||||||
name: row.name.to_owned(),
|
|
||||||
password: row.password.to_owned(),
|
|
||||||
admin: row.admin,
|
|
||||||
enabled: row.enabled,
|
|
||||||
expiration: row.password_expires.0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
@ -115,7 +139,7 @@ pub struct Player {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[typeshare]
|
#[typeshare]
|
||||||
pub struct Game {
|
pub struct Game {
|
||||||
pub id: String,
|
pub id: GameId,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub gm: UserId,
|
pub gm: UserId,
|
||||||
pub players: Vec<UserId>,
|
pub players: Vec<UserId>,
|
||||||
@ -155,6 +179,7 @@ pub struct GameOverview {
|
|||||||
pub players: Vec<UserId>,
|
pub players: Vec<UserId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
impl From<GameRow> for GameOverview {
|
impl From<GameRow> for GameOverview {
|
||||||
fn from(row: GameRow) -> Self {
|
fn from(row: GameRow) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -166,3 +191,4 @@ impl From<GameRow> for GameOverview {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user