From 3edf5d60f54bfd0cd2c818e5fb1ca133e324325d Mon Sep 17 00:00:00 2001 From: Ilion Beyst Date: Thu, 30 Dec 2021 11:45:59 +0100 Subject: rename to planetwars-server --- planetwars-server/src/db/bots.rs | 53 +++++++++++++++++ planetwars-server/src/db/mod.rs | 3 + planetwars-server/src/db/sessions.rs | 46 +++++++++++++++ planetwars-server/src/db/users.rs | 108 +++++++++++++++++++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 planetwars-server/src/db/bots.rs create mode 100644 planetwars-server/src/db/mod.rs create mode 100644 planetwars-server/src/db/sessions.rs create mode 100644 planetwars-server/src/db/users.rs (limited to 'planetwars-server/src/db') diff --git a/planetwars-server/src/db/bots.rs b/planetwars-server/src/db/bots.rs new file mode 100644 index 0000000..bc9cb11 --- /dev/null +++ b/planetwars-server/src/db/bots.rs @@ -0,0 +1,53 @@ +use diesel::prelude::*; +use serde::{Deserialize, Serialize}; + +use crate::schema::{bots, code_bundles}; +use chrono; + +#[derive(Insertable)] +#[table_name = "bots"] +pub struct NewBot<'a> { + pub owner_id: i32, + pub name: &'a str, +} + +#[derive(Queryable, Debug, PartialEq, Serialize, Deserialize)] +pub struct Bot { + pub id: i32, + pub owner_id: i32, + pub name: String, +} + +pub fn create_bot(new_bot: &NewBot, conn: &PgConnection) -> QueryResult { + diesel::insert_into(bots::table) + .values(new_bot) + .get_result(conn) +} + +pub fn find_bot(id: i32, conn: &PgConnection) -> QueryResult { + bots::table.find(id).first(conn) +} + +#[derive(Insertable)] +#[table_name = "code_bundles"] +pub struct NewCodeBundle<'a> { + pub bot_id: i32, + pub path: &'a str, +} + +#[derive(Queryable, Serialize, Deserialize, Debug)] +pub struct CodeBundle { + pub id: i32, + pub bot_id: i32, + pub path: String, + pub created_at: chrono::NaiveDateTime, +} + +pub fn create_code_bundle( + new_code_bundle: &NewCodeBundle, + conn: &PgConnection, +) -> QueryResult { + diesel::insert_into(code_bundles::table) + .values(new_code_bundle) + .get_result(conn) +} diff --git a/planetwars-server/src/db/mod.rs b/planetwars-server/src/db/mod.rs new file mode 100644 index 0000000..947b789 --- /dev/null +++ b/planetwars-server/src/db/mod.rs @@ -0,0 +1,3 @@ +pub mod bots; +pub mod sessions; +pub mod users; diff --git a/planetwars-server/src/db/sessions.rs b/planetwars-server/src/db/sessions.rs new file mode 100644 index 0000000..96f3926 --- /dev/null +++ b/planetwars-server/src/db/sessions.rs @@ -0,0 +1,46 @@ +use super::users::User; +use crate::schema::{sessions, users}; +use base64; +use diesel::PgConnection; +use diesel::{insert_into, prelude::*, Insertable, RunQueryDsl}; +use rand::{self, Rng}; + +#[derive(Insertable)] +#[table_name = "sessions"] +struct NewSession { + token: String, + user_id: i32, +} + +#[derive(Queryable, Debug, PartialEq)] +pub struct Session { + pub id: i32, + pub user_id: i32, + pub token: String, +} + +pub fn create_session(user: &User, conn: &PgConnection) -> Session { + let new_session = NewSession { + token: gen_session_token(), + user_id: user.id, + }; + let session = insert_into(sessions::table) + .values(&new_session) + .get_result::(conn) + .unwrap(); + + return session; +} + +pub fn find_user_by_session(token: &str, conn: &PgConnection) -> QueryResult<(Session, User)> { + sessions::table + .inner_join(users::table) + .filter(sessions::token.eq(&token)) + .first::<(Session, User)>(conn) +} + +pub fn gen_session_token() -> String { + let mut rng = rand::thread_rng(); + let token: [u8; 32] = rng.gen(); + return base64::encode(&token); +} diff --git a/planetwars-server/src/db/users.rs b/planetwars-server/src/db/users.rs new file mode 100644 index 0000000..663f173 --- /dev/null +++ b/planetwars-server/src/db/users.rs @@ -0,0 +1,108 @@ +use crate::schema::users; +use argon2; +use diesel::{prelude::*, PgConnection}; +use rand::Rng; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize)] +pub struct Credentials<'a> { + pub username: &'a str, + pub password: &'a str, +} + +#[derive(Insertable)] +#[table_name = "users"] +pub struct NewUser<'a> { + pub username: &'a str, + pub password_hash: &'a [u8], + pub password_salt: &'a [u8], +} + +#[derive(Queryable, Debug)] +pub struct User { + pub id: i32, + pub username: String, + pub password_salt: Vec, + pub password_hash: Vec, +} + +// TODO: make this configurable somewhere +fn argon2_config() -> argon2::Config<'static> { + argon2::Config { + variant: argon2::Variant::Argon2i, + version: argon2::Version::Version13, + mem_cost: 4096, + time_cost: 3, + lanes: 1, + thread_mode: argon2::ThreadMode::Sequential, + // TODO: set a secret + secret: &[], + ad: &[], + hash_length: 32, + } +} + +pub fn create_user(credentials: &Credentials, conn: &PgConnection) -> QueryResult { + let argon_config = argon2_config(); + + let salt: [u8; 32] = rand::thread_rng().gen(); + let hash = argon2::hash_raw(credentials.password.as_bytes(), &salt, &argon_config).unwrap(); + let new_user = NewUser { + username: &credentials.username, + password_salt: &salt, + password_hash: &hash, + }; + diesel::insert_into(users::table) + .values(&new_user) + .get_result::(conn) +} + +pub fn authenticate_user(credentials: &Credentials, db_conn: &PgConnection) -> Option { + users::table + .filter(users::username.eq(&credentials.username)) + .first::(db_conn) + .optional() + .unwrap() + .and_then(|user| { + let password_matches = argon2::verify_raw( + credentials.password.as_bytes(), + &user.password_salt, + &user.password_hash, + &argon2_config(), + ) + .unwrap(); + + if password_matches { + return Some(user); + } else { + return None; + } + }) +} + +#[test] +fn test_argon() { + let credentials = Credentials { + username: "piepkonijn", + password: "geheim123", + }; + let argon_config = argon2_config(); + + let salt: [u8; 32] = rand::thread_rng().gen(); + let hash = argon2::hash_raw(credentials.password.as_bytes(), &salt, &argon_config).unwrap(); + let new_user = NewUser { + username: &credentials.username, + password_hash: &hash, + password_salt: &salt, + }; + + let password_matches = argon2::verify_raw( + credentials.password.as_bytes(), + &new_user.password_salt, + &new_user.password_hash, + &argon2_config(), + ) + .unwrap(); + + assert!(password_matches); +} -- cgit v1.2.3