From 87f3f31d9d46d0ac597b7c6d58c1b5c36d21aa1a Mon Sep 17 00:00:00 2001 From: Jonni Liljamo Date: Thu, 16 Mar 2023 10:10:03 +0200 Subject: [PATCH] feat(schema, shared, api): move all types to shared, separate schema * schema is now stored in a separate crate to avoid dependency cycles * added note in README.md about handling unwraps --- Cargo.lock | 25 +++++----- Cargo.toml | 1 + README.md | 4 +- api/Cargo.toml | 1 + api/diesel.toml | 2 +- api/src/actions/game/all_forming.rs | 8 ++-- api/src/actions/game/create.rs | 11 ++--- api/src/actions/game/my_games.rs | 5 +- api/src/actions/user/create.rs | 9 ++-- api/src/actions/user/login.rs | 9 ++-- api/src/handlers/user/create.rs | 6 +-- api/src/handlers/user/login.rs | 4 +- api/src/main.rs | 3 -- api/src/models/action.rs | 34 ------------- api/src/models/game.rs | 36 -------------- api/src/models/gamedata.rs | 36 -------------- api/src/models/mod.rs | 19 -------- api/src/models/user.rs | 40 ---------------- schema/Cargo.toml | 17 +++++++ schema/LICENSE | 8 ++++ schema/src/lib.rs | 9 ++++ {api => schema}/src/schema.rs | 0 shared/Cargo.toml | 23 ++++++++- shared/src/api/user/mod.rs | 6 +-- shared/src/types/game.rs | 74 +++++++++++++++++++++++++++++ shared/src/types/user.rs | 40 ++++++++++++++-- 26 files changed, 211 insertions(+), 219 deletions(-) delete mode 100644 api/src/models/action.rs delete mode 100644 api/src/models/game.rs delete mode 100644 api/src/models/gamedata.rs delete mode 100644 api/src/models/mod.rs delete mode 100644 api/src/models/user.rs create mode 100644 schema/Cargo.toml create mode 100644 schema/LICENSE create mode 100644 schema/src/lib.rs rename {api => schema}/src/schema.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 86180cc..1339fc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -546,6 +546,7 @@ dependencies = [ "email_address", "log", "pretty_env_logger", + "schema", "serde", "serde_json", "shared", @@ -5225,6 +5226,13 @@ dependencies = [ "parking_lot 0.12.1", ] +[[package]] +name = "schema" +version = "0.1.0" +dependencies = [ + "diesel", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -5343,17 +5351,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_repr" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "serde_spanned" version = "0.6.1" @@ -5448,11 +5445,15 @@ dependencies = [ name = "shared" version = "0.1.0" dependencies = [ + "chrono", + "diesel", "naia-bevy-shared", "reqwest", + "schema", "serde", - "serde_repr", + "serde_json", "thiserror", + "uuid 1.3.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e0762d7..d8f7fbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ resolver = "2" members = [ + "schema", "shared", "client", "server", diff --git a/README.md b/README.md index 9320c84..61fefb2 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ and just send an event to the client with the new one, so they can update\ it in the clients presistent storage, right? This can happen automatically\ in the background. +### **Quite a few unwraps in use** +All should be handled, with sane error responses. ## **Shortest possible explanation of the structure** ``` @@ -59,4 +61,4 @@ Commits after 09.01.2023 MUST follow [Conventional Commits 1.0.0](https://www.co Things to remember: * everything lowercase -* allowed scopes are `shared`, `client`, `server` and `api` +* allowed scopes are `schema`, `shared`, `client`, `server` and `api` diff --git a/api/Cargo.toml b/api/Cargo.toml index 3e0cfb7..8b8058a 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-only" publish = false [dependencies] +laurelin_schema = { package = "schema", path = "../schema" } laurelin_shared = { package = "shared", path = "../shared" } log = "0.4.17" diff --git a/api/diesel.toml b/api/diesel.toml index 35a12ff..9295974 100644 --- a/api/diesel.toml +++ b/api/diesel.toml @@ -2,7 +2,7 @@ # see https://diesel.rs/guides/configuring-diesel-cli [print_schema] -file = "src/schema.rs" +file = "../schema/src/schema.rs" [migrations_directory] dir = "migrations" diff --git a/api/src/actions/game/all_forming.rs b/api/src/actions/game/all_forming.rs index c528376..5a41380 100644 --- a/api/src/actions/game/all_forming.rs +++ b/api/src/actions/game/all_forming.rs @@ -7,9 +7,11 @@ */ use diesel::{ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl}; -use laurelin_shared::{error::api::APIError, types::game::GAMESTATE_FORMING}; - -use crate::{models::Game, schema::games}; +use laurelin_schema::schema::games; +use laurelin_shared::{ + error::api::APIError, + types::game::{Game, GAMESTATE_FORMING}, +}; pub(crate) fn all_forming(conn: &mut PgConnection) -> Result, APIError> { let games_res = games::table diff --git a/api/src/actions/game/create.rs b/api/src/actions/game/create.rs index 050b6a5..4957cc5 100644 --- a/api/src/actions/game/create.rs +++ b/api/src/actions/game/create.rs @@ -7,13 +7,12 @@ */ use diesel::{PgConnection, RunQueryDsl}; -use laurelin_shared::{error::api::APIError, types::game::GAMESTATE_FORMING}; -use uuid::Uuid; - -use crate::{ - models::{Game, GameData, InsertableGame, InsertableGameData}, - schema::{gamedata, games}, +use laurelin_schema::schema::{gamedata, games}; +use laurelin_shared::{ + error::api::APIError, + types::game::{Game, GameData, InsertableGame, InsertableGameData, GAMESTATE_FORMING}, }; +use uuid::Uuid; pub(crate) fn create(conn: &mut PgConnection, user_id: &str) -> Result { let new_gamedata = InsertableGameData { diff --git a/api/src/actions/game/my_games.rs b/api/src/actions/game/my_games.rs index f90a522..b37a742 100644 --- a/api/src/actions/game/my_games.rs +++ b/api/src/actions/game/my_games.rs @@ -7,11 +7,10 @@ */ use diesel::{BoolExpressionMethods, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl}; -use laurelin_shared::error::api::APIError; +use laurelin_schema::schema::games; +use laurelin_shared::{error::api::APIError, types::game::Game}; use uuid::Uuid; -use crate::{models::Game, schema::games}; - pub(crate) fn my_games(conn: &mut PgConnection, user_id: &str) -> Result, APIError> { let games_res = games::table .filter( diff --git a/api/src/actions/user/create.rs b/api/src/actions/user/create.rs index 3da41f8..4e7d081 100644 --- a/api/src/actions/user/create.rs +++ b/api/src/actions/user/create.rs @@ -11,11 +11,10 @@ use argon2::{ Argon2, PasswordHasher, }; use diesel::{ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl}; -use laurelin_shared::error::api::APIError; - -use crate::{ - models::{InsertableUser, User}, - schema::users, +use laurelin_schema::schema::users; +use laurelin_shared::{ + error::api::APIError, + types::user::{InsertableUser, User}, }; pub(crate) fn create(conn: &mut PgConnection, user: &InsertableUser) -> Result { diff --git a/api/src/actions/user/login.rs b/api/src/actions/user/login.rs index e3158b3..b8b10ce 100644 --- a/api/src/actions/user/login.rs +++ b/api/src/actions/user/login.rs @@ -8,11 +8,10 @@ use argon2::{Argon2, PasswordHash, PasswordVerifier}; use diesel::{ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl}; -use laurelin_shared::error::api::APIError; - -use crate::{ - models::{User, UserCredentials}, - schema::users, +use laurelin_schema::schema::users; +use laurelin_shared::{ + error::api::APIError, + types::user::{User, UserCredentials}, }; pub(crate) fn login( diff --git a/api/src/handlers/user/create.rs b/api/src/handlers/user/create.rs index dcee18a..8531084 100644 --- a/api/src/handlers/user/create.rs +++ b/api/src/handlers/user/create.rs @@ -10,15 +10,15 @@ use actix_session::Session; use actix_web::{post, web, HttpResponse, Responder}; use email_address::EmailAddress; -use laurelin_shared::error::api::APIError; +use laurelin_shared::{error::api::APIError, types::user::InsertableUser}; -use crate::{actions, models, PgPool}; +use crate::{actions, PgPool}; #[post("/api/user")] pub(crate) async fn create( pool: web::Data, session: Session, - user: web::Json, + user: web::Json, ) -> impl Responder { if user.username.len() < 3 { return HttpResponse::BadRequest().json(APIError::UserUsernameTooShort); diff --git a/api/src/handlers/user/login.rs b/api/src/handlers/user/login.rs index 09ea600..ffada7f 100644 --- a/api/src/handlers/user/login.rs +++ b/api/src/handlers/user/login.rs @@ -8,9 +8,9 @@ use actix_session::Session; use actix_web::{post, web, HttpResponse, Responder}; -use laurelin_shared::error::api::APIError; +use laurelin_shared::{error::api::APIError, types::user::UserCredentials}; -use crate::{actions, models::UserCredentials, PgPool}; +use crate::{actions, PgPool}; #[post("/api/user/login")] pub(crate) async fn login( diff --git a/api/src/main.rs b/api/src/main.rs index 46f73f5..96170ab 100644 --- a/api/src/main.rs +++ b/api/src/main.rs @@ -52,11 +52,8 @@ fn run_migrations(conn: &mut PgConnection) { conn.run_pending_migrations(MIGRATIONS).unwrap(); } -mod schema; - mod actions; mod handlers; -mod models; mod session; #[actix_web::main] diff --git a/api/src/models/action.rs b/api/src/models/action.rs deleted file mode 100644 index 3b819b3..0000000 --- a/api/src/models/action.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of laurelin/api - * Copyright (C) 2023 Jonni Liljamo - * - * Licensed under GPL-3.0-only. - * See LICENSE for licensing information. - */ - -use chrono::NaiveDateTime; -use diesel::{Insertable, Queryable}; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -use crate::schema::actions; - -#[derive(Serialize, Queryable)] -pub(crate) struct Action { - pub id: Uuid, - pub created_at: NaiveDateTime, - pub updated_at: NaiveDateTime, - pub game_data_id: Uuid, - pub invoker: Uuid, - pub data: serde_json::Value, - pub timestamp: NaiveDateTime, -} - -#[derive(Deserialize, Insertable)] -#[diesel(table_name=actions)] -pub(crate) struct InsertableAction { - pub game_data_id: Uuid, - pub invoker: Uuid, - pub data: serde_json::Value, - pub timestamp: NaiveDateTime, -} diff --git a/api/src/models/game.rs b/api/src/models/game.rs deleted file mode 100644 index 81c87e1..0000000 --- a/api/src/models/game.rs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of laurelin/api - * Copyright (C) 2023 Jonni Liljamo - * - * Licensed under GPL-3.0-only. - * See LICENSE for licensing information. - */ - -use chrono::NaiveDateTime; -use diesel::{Insertable, Queryable}; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -use crate::schema::games; - -#[derive(Serialize, Queryable)] -pub(crate) struct Game { - pub id: Uuid, - pub created_at: NaiveDateTime, - pub updated_at: NaiveDateTime, - pub host_id: Uuid, - pub guest_id: Option, - pub state: i16, - pub ended_at: Option, - pub game_data_id: Uuid, -} - -#[derive(Deserialize, Insertable)] -#[diesel(table_name=games)] -pub(crate) struct InsertableGame { - pub host_id: Uuid, - pub guest_id: Option, - pub state: i16, - pub ended_at: Option, - pub game_data_id: Uuid, -} diff --git a/api/src/models/gamedata.rs b/api/src/models/gamedata.rs deleted file mode 100644 index 857a241..0000000 --- a/api/src/models/gamedata.rs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of laurelin/api - * Copyright (C) 2023 Jonni Liljamo - * - * Licensed under GPL-3.0-only. - * See LICENSE for licensing information. - */ - -use chrono::NaiveDateTime; -use diesel::{Insertable, Queryable}; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -use crate::schema::gamedata; - -#[derive(Serialize, Queryable)] -pub(crate) struct GameData { - pub id: Uuid, - pub created_at: NaiveDateTime, - pub updated_at: NaiveDateTime, - pub turn: i16, - pub host_hand: Option, - pub host_deck: Option, - pub guest_hand: Option, - pub guest_deck: Option, -} - -#[derive(Deserialize, Insertable)] -#[diesel(table_name=gamedata)] -pub(crate) struct InsertableGameData { - pub turn: i16, - pub host_hand: Option, - pub host_deck: Option, - pub guest_hand: Option, - pub guest_deck: Option, -} diff --git a/api/src/models/mod.rs b/api/src/models/mod.rs deleted file mode 100644 index 2ea9cda..0000000 --- a/api/src/models/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of laurelin/api - * Copyright (C) 2023 Jonni Liljamo - * - * Licensed under GPL-3.0-only. - * See LICENSE for licensing information. - */ - -mod user; -pub(crate) use user::*; - -mod action; -pub(crate) use action::*; - -mod game; -pub(crate) use game::*; - -mod gamedata; -pub(crate) use gamedata::*; diff --git a/api/src/models/user.rs b/api/src/models/user.rs deleted file mode 100644 index 6e01fc6..0000000 --- a/api/src/models/user.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of laurelin/api - * Copyright (C) 2023 Jonni Liljamo - * - * Licensed under GPL-3.0-only. - * See LICENSE for licensing information. - */ - -use chrono::NaiveDateTime; -use diesel::{Insertable, Queryable}; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -use crate::schema::users; - -#[derive(Serialize, Queryable)] -pub(crate) struct User { - pub id: Uuid, - pub created_at: NaiveDateTime, - pub updated_at: NaiveDateTime, - pub username: String, - pub email: String, - #[allow(dead_code)] - #[serde(skip_serializing)] - pub password: String, -} - -#[derive(Deserialize, Insertable)] -#[diesel(table_name=users)] -pub(crate) struct InsertableUser { - pub username: String, - pub email: String, - pub password: String, -} - -#[derive(Deserialize)] -pub(crate) struct UserCredentials { - pub email: String, - pub password: String, -} diff --git a/schema/Cargo.toml b/schema/Cargo.toml new file mode 100644 index 0000000..6c26dae --- /dev/null +++ b/schema/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "schema" +version = "0.1.0" +authors = ["Jonni Liljamo "] +edition = "2021" +description = "Schema for laurelin" +readme = "README.md" +repository = "https://git.src.quest/~skye/deck-builder/" +license = "GPL-3.0-only" +publish = false + +[dependencies] + +[dependencies.diesel] +version = "2.0.3" +default-features = false +features = [ "with-deprecated", "32-column-tables", "postgres", "r2d2", "chrono", "uuid", "serde_json" ] diff --git a/schema/LICENSE b/schema/LICENSE new file mode 100644 index 0000000..c589a60 --- /dev/null +++ b/schema/LICENSE @@ -0,0 +1,8 @@ +Schema for a deck building game. +Copyright (C) 2023 Jonni Liljamo + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. If not, see . diff --git a/schema/src/lib.rs b/schema/src/lib.rs new file mode 100644 index 0000000..eba77c4 --- /dev/null +++ b/schema/src/lib.rs @@ -0,0 +1,9 @@ +/* + * This file is part of laurelin/schema + * Copyright (C) 2023 Jonni Liljamo + * + * Licensed under GPL-3.0-only. + * See LICENSE for licensing information. + */ + +pub mod schema; diff --git a/api/src/schema.rs b/schema/src/schema.rs similarity index 100% rename from api/src/schema.rs rename to schema/src/schema.rs diff --git a/shared/Cargo.toml b/shared/Cargo.toml index af63fc0..dfe8ce1 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -10,15 +10,34 @@ license = "GPL-3.0-only" publish = false [dependencies] +laurelin_schema = { package = "schema", path = "../schema" } + naia-bevy-shared = "0.19.0" thiserror = "1.0.38" reqwest = { version = "0.11.14", features = ["blocking", "json", "cookies" ] } -serde_repr = "0.1.10" - [dependencies.serde] version = "1.0.152" default-features = false features = [ "derive" ] + +[dependencies.serde_json] +version = "1.0.94" +default-features = false +features = [ "std" ] + +[dependencies.chrono] +version = "0.4.23" +default-features = false +features = [ "alloc", "std", "serde" ] + +[dependencies.diesel] +version = "2.0.3" +default-features = false +features = [ "with-deprecated", "32-column-tables", "postgres", "r2d2", "chrono", "uuid", "serde_json" ] + +[dependencies.uuid] +version = "1.3.0" +features = [ "std", "v4", "serde" ] diff --git a/shared/src/api/user/mod.rs b/shared/src/api/user/mod.rs index 23cda35..b24f770 100644 --- a/shared/src/api/user/mod.rs +++ b/shared/src/api/user/mod.rs @@ -9,7 +9,7 @@ use reqwest; use serde::{Deserialize, Serialize}; -use crate::{error::api::APIError, types::user::User}; +use crate::{error::api::APIError, types::user::UserPub}; use super::macros::extract_cookie; @@ -23,7 +23,7 @@ pub struct PostLogin { #[serde(untagged)] pub enum ResponseLogin { Error(APIError), - Ok(User), + Ok(UserPub), } #[derive(Deserialize)] @@ -61,7 +61,7 @@ pub struct PostRegister { #[serde(untagged)] pub enum ResponseRegister { Error(APIError), - Ok(User), + Ok(UserPub), } #[derive(Deserialize)] diff --git a/shared/src/types/game.rs b/shared/src/types/game.rs index e028f6a..77dac9e 100644 --- a/shared/src/types/game.rs +++ b/shared/src/types/game.rs @@ -6,7 +6,81 @@ * See LICENSE for licensing information. */ +use chrono::NaiveDateTime; +use diesel::{Insertable, Queryable}; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use laurelin_schema::schema::{actions, gamedata, games}; + pub const GAMESTATE_FORMING: i16 = 0; pub const GAMESTATE_INPROGRESS: i16 = 1; pub const GAMESTATE_FINISHED: i16 = 2; pub const GAMESTATE_CANCELLED: i16 = 3; + +pub const GAMETURN_HOST: i16 = 0; +pub const GAMETURN_GUEST: i16 = 1; + +#[derive(Serialize, Deserialize, Queryable)] +pub struct Game { + pub id: Uuid, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, + pub host_id: Uuid, + pub guest_id: Option, + pub state: i16, + pub ended_at: Option, + pub game_data_id: Uuid, +} + +#[derive(Deserialize, Insertable)] +#[diesel(table_name=games)] +pub struct InsertableGame { + pub host_id: Uuid, + pub guest_id: Option, + pub state: i16, + pub ended_at: Option, + pub game_data_id: Uuid, +} + +#[derive(Serialize, Deserialize, Queryable)] +pub struct Action { + pub id: Uuid, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, + pub game_data_id: Uuid, + pub invoker: Uuid, + pub data: serde_json::Value, + pub timestamp: NaiveDateTime, +} + +#[derive(Deserialize, Insertable)] +#[diesel(table_name=actions)] +pub struct InsertableAction { + pub game_data_id: Uuid, + pub invoker: Uuid, + pub data: serde_json::Value, + pub timestamp: NaiveDateTime, +} + +#[derive(Serialize, Deserialize, Queryable)] +pub struct GameData { + pub id: Uuid, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, + pub turn: i16, + pub host_hand: Option, + pub host_deck: Option, + pub guest_hand: Option, + pub guest_deck: Option, +} + +#[derive(Deserialize, Insertable)] +#[diesel(table_name=gamedata)] +pub struct InsertableGameData { + pub turn: i16, + pub host_hand: Option, + pub host_deck: Option, + pub guest_hand: Option, + pub guest_deck: Option, +} diff --git a/shared/src/types/user.rs b/shared/src/types/user.rs index 5d63a34..8a3697d 100644 --- a/shared/src/types/user.rs +++ b/shared/src/types/user.rs @@ -6,13 +6,43 @@ * See LICENSE for licensing information. */ -use serde::Deserialize; +use chrono::NaiveDateTime; +use diesel::{Insertable, Queryable}; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; -#[derive(Deserialize)] +use laurelin_schema::schema::users; + +#[derive(Serialize, Deserialize, Queryable)] pub struct User { - pub id: String, - pub created_at: String, - pub updated_at: String, + pub id: Uuid, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, + pub username: String, + pub email: String, + #[serde(skip_serializing)] + pub password: String, +} + +#[derive(Deserialize)] +pub struct UserPub { + pub id: Uuid, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, pub username: String, pub email: String, } + +#[derive(Deserialize, Insertable)] +#[diesel(table_name=users)] +pub struct InsertableUser { + pub username: String, + pub email: String, + pub password: String, +} + +#[derive(Deserialize)] +pub struct UserCredentials { + pub email: String, + pub password: String, +} -- 2.44.1