Set up the user interface state model and set up the admin user onboarding #283
|
@ -0,0 +1,16 @@
|
||||||
|
CREATE TABLE users(
|
||||||
|
uuid TEXT PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
password TEXT,
|
||||||
|
admin BOOLEAN,
|
||||||
|
enabled BOOLEAN
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE roles(
|
||||||
|
user_id TEXT,
|
||||||
|
game_id TEXT,
|
||||||
|
role TEXT,
|
||||||
|
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(uuid),
|
||||||
|
FOREIGN KEY(game_id) REFERENCES games(uuid)
|
||||||
|
);
|
|
@ -48,12 +48,62 @@ enum DatabaseResponse {
|
||||||
Charsheet(Option<CharsheetRow>),
|
Charsheet(Option<CharsheetRow>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||||
|
pub struct UserId(String);
|
||||||
|
|
||||||
|
impl UserId {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(format!("{}", Uuid::new_v4().hyphenated()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_str<'a>(&'a self) -> &'a str {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for UserId {
|
||||||
|
fn from(s: &str) -> Self {
|
||||||
|
Self(s.to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for UserId {
|
||||||
|
fn from(s: String) -> Self {
|
||||||
|
Self(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||||
|
pub struct GameId(String);
|
||||||
|
|
||||||
|
impl GameId {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(format!("{}", Uuid::new_v4().hyphenated()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_str<'a>(&'a self) -> &'a str {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for GameId {
|
||||||
|
fn from(s: &str) -> Self {
|
||||||
|
Self(s.to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for GameId {
|
||||||
|
fn from(s: String) -> Self {
|
||||||
|
Self(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||||
pub struct CharacterId(String);
|
pub struct CharacterId(String);
|
||||||
|
|
||||||
impl CharacterId {
|
impl CharacterId {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
CharacterId(format!("{}", Uuid::new_v4().hyphenated()))
|
Self(format!("{}", Uuid::new_v4().hyphenated()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_str<'a>(&'a self) -> &'a str {
|
pub fn as_str<'a>(&'a self) -> &'a str {
|
||||||
|
@ -63,20 +113,36 @@ impl CharacterId {
|
||||||
|
|
||||||
impl From<&str> for CharacterId {
|
impl From<&str> for CharacterId {
|
||||||
fn from(s: &str) -> Self {
|
fn from(s: &str) -> Self {
|
||||||
CharacterId(s.to_owned())
|
Self(s.to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for CharacterId {
|
impl From<String> for CharacterId {
|
||||||
fn from(s: String) -> Self {
|
fn from(s: String) -> Self {
|
||||||
CharacterId(s)
|
Self(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct UserRow {
|
||||||
|
id: String,
|
||||||
|
name: String,
|
||||||
|
password: String,
|
||||||
|
admin: bool,
|
||||||
|
enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Role {
|
||||||
|
userid: String,
|
||||||
|
gameid: String,
|
||||||
|
role: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CharsheetRow {
|
pub struct CharsheetRow {
|
||||||
id: String,
|
id: String,
|
||||||
gametype: String,
|
game: String,
|
||||||
pub data: serde_json::Value,
|
pub data: serde_json::Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,11 +159,20 @@ fn setup_test_database(conn: &Connection) {
|
||||||
let mut gamecount_stmt = conn.prepare("SELECT count(*) FROM games").unwrap();
|
let mut gamecount_stmt = conn.prepare("SELECT count(*) FROM games").unwrap();
|
||||||
let mut count = gamecount_stmt.query([]).unwrap();
|
let mut count = gamecount_stmt.query([]).unwrap();
|
||||||
if count.next().unwrap().unwrap().get::<usize, usize>(0) == Ok(0) {
|
if count.next().unwrap().unwrap().get::<usize, usize>(0) == Ok(0) {
|
||||||
|
let admin_id = format!("{}", Uuid::new_v4());
|
||||||
|
let user_id = format!("{}", Uuid::new_v4());
|
||||||
let game_id = format!("{}", Uuid::new_v4());
|
let game_id = format!("{}", Uuid::new_v4());
|
||||||
let char_id = CharacterId::new();
|
let char_id = CharacterId::new();
|
||||||
|
|
||||||
|
let mut user_stmt = conn.prepare("INSERT INTO users VALUES (?, ?, ?, ?, ?)").unwrap();
|
||||||
|
user_stmt.execute((admin_id.clone(), "admin", "abcdefg", true, true)).unwrap();
|
||||||
|
user_stmt.execute((user_id.clone(), "savanni", "abcdefg", false, true)).unwrap();
|
||||||
|
|
||||||
let mut game_stmt = conn.prepare("INSERT INTO games VALUES (?, ?)").unwrap();
|
let mut game_stmt = conn.prepare("INSERT INTO games VALUES (?, ?)").unwrap();
|
||||||
game_stmt.execute((game_id.clone(), "Circle of Bluest Sky"));
|
game_stmt.execute((game_id.clone(), "Circle of Bluest Sky")).unwrap();
|
||||||
|
|
||||||
|
let mut role_stmt = conn.prepare("INSERT INTO roles VALUES (?, ?, ?)").unwrap();
|
||||||
|
role_stmt.execute((user_id.clone(), game_id.clone(), "gm")).unwrap();
|
||||||
|
|
||||||
let mut sheet_stmt = conn
|
let mut sheet_stmt = conn
|
||||||
.prepare("INSERT INTO characters VALUES (?, ?, ?)")
|
.prepare("INSERT INTO characters VALUES (?, ?, ?)")
|
||||||
|
@ -124,17 +199,37 @@ impl DiskDb {
|
||||||
Ok(DiskDb { conn })
|
Ok(DiskDb { conn })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn user(&self, id: UserId) -> Result<Option<UserRow>, Error> {
|
||||||
|
let mut stmt = self
|
||||||
|
.conn
|
||||||
|
.prepare("SELECT uuid, name, password, admin, enabled WHERE uuid=?")
|
||||||
|
.unwrap();
|
||||||
|
let items: Vec<UserRow> = stmt
|
||||||
|
.query_map([id.as_str()], |row| Ok(UserRow {
|
||||||
|
id: row.get(0).unwrap(),
|
||||||
|
name: row.get(1).unwrap(),
|
||||||
|
password: row.get(2).unwrap(),
|
||||||
|
admin: row.get(3).unwrap(),
|
||||||
|
enabled: row.get(4).unwrap(),
|
||||||
|
})).unwrap().collect::<Result<Vec<UserRow>, rusqlite::Error>>().unwrap();
|
||||||
|
match &items[..] {
|
||||||
|
[] => Ok(None),
|
||||||
|
[item] => Ok(Some(item.clone())),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn charsheet(&self, id: CharacterId) -> Result<Option<CharsheetRow>, Error> {
|
fn charsheet(&self, id: CharacterId) -> Result<Option<CharsheetRow>, Error> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.conn
|
.conn
|
||||||
.prepare("SELECT uuid, gametype, data FROM charsheet WHERE uuid=?")
|
.prepare("SELECT uuid, game, data FROM charsheet WHERE uuid=?")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let items: Vec<CharsheetRow> = stmt
|
let items: Vec<CharsheetRow> = stmt
|
||||||
.query_map([id.as_str()], |row| {
|
.query_map([id.as_str()], |row| {
|
||||||
let data: String = row.get(2).unwrap();
|
let data: String = row.get(2).unwrap();
|
||||||
Ok(CharsheetRow {
|
Ok(CharsheetRow {
|
||||||
id: row.get(0).unwrap(),
|
id: row.get(0).unwrap(),
|
||||||
gametype: row.get(1).unwrap(),
|
game: row.get(1).unwrap(),
|
||||||
data: serde_json::from_str(&data).unwrap(),
|
data: serde_json::from_str(&data).unwrap(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue