M Cargo.lock => Cargo.lock +13 -12
@@ 546,6 546,7 @@ dependencies = [
"email_address",
"log",
"pretty_env_logger",
+ "schema",
"serde",
"serde_json",
"shared",
@@ 5226,6 5227,13 @@ dependencies = [
]
[[package]]
+name = "schema"
+version = "0.1.0"
+dependencies = [
+ "diesel",
+]
+
+[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 5344,17 5352,6 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 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]]
M Cargo.toml => Cargo.toml +1 -0
@@ 2,6 2,7 @@
resolver = "2"
members = [
+ "schema",
"shared",
"client",
"server",
M README.md => README.md +3 -1
@@ 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`
M api/Cargo.toml => api/Cargo.toml +1 -0
@@ 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"
M api/diesel.toml => api/diesel.toml +1 -1
@@ 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"
M api/src/actions/game/all_forming.rs => api/src/actions/game/all_forming.rs +5 -3
@@ 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<Vec<Game>, APIError> {
let games_res = games::table
M api/src/actions/game/create.rs => api/src/actions/game/create.rs +5 -6
@@ 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<Game, APIError> {
let new_gamedata = InsertableGameData {
M api/src/actions/game/my_games.rs => api/src/actions/game/my_games.rs +2 -3
@@ 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<Vec<Game>, APIError> {
let games_res = games::table
.filter(
M api/src/actions/user/create.rs => api/src/actions/user/create.rs +4 -5
@@ 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<User, APIError> {
M api/src/actions/user/login.rs => api/src/actions/user/login.rs +4 -5
@@ 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(
M api/src/handlers/user/create.rs => api/src/handlers/user/create.rs +3 -3
@@ 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<PgPool>,
session: Session,
- user: web::Json<models::InsertableUser>,
+ user: web::Json<InsertableUser>,
) -> impl Responder {
if user.username.len() < 3 {
return HttpResponse::BadRequest().json(APIError::UserUsernameTooShort);
M api/src/handlers/user/login.rs => api/src/handlers/user/login.rs +2 -2
@@ 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(
M api/src/main.rs => api/src/main.rs +0 -3
@@ 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]
D api/src/models/action.rs => api/src/models/action.rs +0 -34
@@ 1,34 0,0 @@
-/*
- * This file is part of laurelin/api
- * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
- *
- * 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,
-}
D api/src/models/game.rs => api/src/models/game.rs +0 -36
@@ 1,36 0,0 @@
-/*
- * This file is part of laurelin/api
- * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
- *
- * 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<Uuid>,
- pub state: i16,
- pub ended_at: Option<NaiveDateTime>,
- pub game_data_id: Uuid,
-}
-
-#[derive(Deserialize, Insertable)]
-#[diesel(table_name=games)]
-pub(crate) struct InsertableGame {
- pub host_id: Uuid,
- pub guest_id: Option<Uuid>,
- pub state: i16,
- pub ended_at: Option<NaiveDateTime>,
- pub game_data_id: Uuid,
-}
D api/src/models/gamedata.rs => api/src/models/gamedata.rs +0 -36
@@ 1,36 0,0 @@
-/*
- * This file is part of laurelin/api
- * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
- *
- * 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<serde_json::Value>,
- pub host_deck: Option<serde_json::Value>,
- pub guest_hand: Option<serde_json::Value>,
- pub guest_deck: Option<serde_json::Value>,
-}
-
-#[derive(Deserialize, Insertable)]
-#[diesel(table_name=gamedata)]
-pub(crate) struct InsertableGameData {
- pub turn: i16,
- pub host_hand: Option<serde_json::Value>,
- pub host_deck: Option<serde_json::Value>,
- pub guest_hand: Option<serde_json::Value>,
- pub guest_deck: Option<serde_json::Value>,
-}
D api/src/models/user.rs => api/src/models/user.rs +0 -40
@@ 1,40 0,0 @@
-/*
- * This file is part of laurelin/api
- * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
- *
- * 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,
-}
A schema/Cargo.toml => schema/Cargo.toml +17 -0
@@ 0,0 1,17 @@
+[package]
+name = "schema"
+version = "0.1.0"
+authors = ["Jonni Liljamo <jonni@liljamo.com>"]
+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" ]
A schema/LICENSE => schema/LICENSE +8 -0
@@ 0,0 1,8 @@
+Schema for a deck building game.
+Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
+
+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 <http://www.gnu.org/licenses/>.
R api/src/models/mod.rs => schema/src/lib.rs +2 -12
@@ 1,19 1,9 @@
/*
- * This file is part of laurelin/api
+ * This file is part of laurelin/schema
* Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
*
* 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::*;
+pub mod schema;
R api/src/schema.rs => schema/src/schema.rs +0 -0
M shared/Cargo.toml => shared/Cargo.toml +21 -2
@@ 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" ]
M shared/src/api/user/mod.rs => shared/src/api/user/mod.rs +3 -3
@@ 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)]
M shared/src/types/game.rs => shared/src/types/game.rs +74 -0
@@ 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<Uuid>,
+ pub state: i16,
+ pub ended_at: Option<NaiveDateTime>,
+ pub game_data_id: Uuid,
+}
+
+#[derive(Deserialize, Insertable)]
+#[diesel(table_name=games)]
+pub struct InsertableGame {
+ pub host_id: Uuid,
+ pub guest_id: Option<Uuid>,
+ pub state: i16,
+ pub ended_at: Option<NaiveDateTime>,
+ 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<serde_json::Value>,
+ pub host_deck: Option<serde_json::Value>,
+ pub guest_hand: Option<serde_json::Value>,
+ pub guest_deck: Option<serde_json::Value>,
+}
+
+#[derive(Deserialize, Insertable)]
+#[diesel(table_name=gamedata)]
+pub struct InsertableGameData {
+ pub turn: i16,
+ pub host_hand: Option<serde_json::Value>,
+ pub host_deck: Option<serde_json::Value>,
+ pub guest_hand: Option<serde_json::Value>,
+ pub guest_deck: Option<serde_json::Value>,
+}
M shared/src/types/user.rs => shared/src/types/user.rs +35 -5
@@ 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,
+}