diff --git a/.env b/.env
new file mode 100644
index 0000000..ebec27a
--- /dev/null
+++ b/.env
@@ -0,0 +1 @@
+DATABASE_URL=postgres://postgres:postgres@localhost/hotel
diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 0000000..a03d898
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ postgresql
+ true
+ org.postgresql.Driver
+ jdbc:postgresql://localhost:5432/hotel
+ $ProjectFileDir$
+
+
+
\ No newline at end of file
diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml
new file mode 100644
index 0000000..6df4889
--- /dev/null
+++ b/.idea/sqldialects.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index e94041a..1bc0094 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -295,6 +295,12 @@ dependencies = [
"alloc-stdlib",
]
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
[[package]]
name = "bytes"
version = "1.4.0"
@@ -394,6 +400,43 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "diesel"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4391a22b19c916e50bec4d6140f29bdda3e3bb187223fe6e3ea0b6e4d1021c04"
+dependencies = [
+ "bitflags",
+ "byteorder",
+ "diesel_derives",
+ "itoa",
+ "pq-sys",
+ "r2d2",
+]
+
+[[package]]
+name = "diesel_derives"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ad74fdcf086be3d4fdd142f67937678fe60ed431c3b2f08599e7687269410c4"
+dependencies = [
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "diesel_migrations"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9ae22beef5e9d6fab9225ddb073c1c6c1a7a6ded5019d5da11d1e5c5adc34e2"
+dependencies = [
+ "diesel",
+ "migrations_internals",
+ "migrations_macros",
+]
+
[[package]]
name = "digest"
version = "0.10.6"
@@ -404,6 +447,12 @@ dependencies = [
"crypto-common",
]
+[[package]]
+name = "dotenvy"
+version = "0.15.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
+
[[package]]
name = "encoding_rs"
version = "0.8.32"
@@ -438,65 +487,12 @@ dependencies = [
"percent-encoding",
]
-[[package]]
-name = "futures"
-version = "0.3.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
[[package]]
name = "futures-core"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
-[[package]]
-name = "futures-executor"
-version = "0.3.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
[[package]]
name = "futures-sink"
version = "0.3.27"
@@ -515,16 +511,10 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab"
dependencies = [
- "futures-channel",
"futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
"futures-task",
- "memchr",
"pin-project-lite",
"pin-utils",
- "slab",
]
[[package]]
@@ -596,12 +586,15 @@ name = "hotel"
version = "0.1.0"
dependencies = [
"actix-web",
- "futures",
+ "diesel",
+ "diesel_migrations",
+ "dotenvy",
"log",
"once_cell",
+ "r2d2",
"serde",
"simple_logger",
- "toml",
+ "toml 0.7.3",
]
[[package]]
@@ -723,6 +716,27 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+[[package]]
+name = "migrations_internals"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c493c09323068c01e54c685f7da41a9ccf9219735c3766fbfd6099806ea08fbc"
+dependencies = [
+ "serde",
+ "toml 0.5.11",
+]
+
+[[package]]
+name = "migrations_macros"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a8ff27a350511de30cdabb77147501c36ef02e0451d957abea2f30caffb2b58"
+dependencies = [
+ "migrations_internals",
+ "proc-macro2",
+ "quote",
+]
+
[[package]]
name = "mime"
version = "0.3.17"
@@ -834,6 +848,39 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+[[package]]
+name = "pq-sys"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b845d6d8ec554f972a2c5298aad68953fd64e7441e846075450b44656a016d1"
+dependencies = [
+ "vcpkg",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
[[package]]
name = "proc-macro2"
version = "1.0.53"
@@ -852,6 +899,17 @@ dependencies = [
"proc-macro2",
]
+[[package]]
+name = "r2d2"
+version = "0.8.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93"
+dependencies = [
+ "log",
+ "parking_lot",
+ "scheduled-thread-pool",
+]
+
[[package]]
name = "rand"
version = "0.8.5"
@@ -923,6 +981,15 @@ version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+[[package]]
+name = "scheduled-thread-pool"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19"
+dependencies = [
+ "parking_lot",
+]
+
[[package]]
name = "scopeguard"
version = "1.1.0"
@@ -1143,6 +1210,15 @@ dependencies = [
"tracing",
]
+[[package]]
+name = "toml"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "toml"
version = "0.7.3"
@@ -1236,6 +1312,12 @@ dependencies = [
"percent-encoding",
]
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
[[package]]
name = "version_check"
version = "0.9.4"
diff --git a/Cargo.toml b/Cargo.toml
index 3e156cd..1f06a5a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,10 +6,17 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-actix-web = "4"
-serde = { version = "1.0.158", features = ["derive"] }
-futures = "0.3.27"
-once_cell = "1.17.1"
-toml = "0.7.3"
-log = "0.4.17"
-simple_logger = "4.1.0"
\ No newline at end of file
+actix-web = "4" # Web framework
+
+serde = { version = "1.0.158", features = ["derive"] } # Serialization and deserialization
+
+once_cell = "1.17.1" # Config
+toml = "0.7.3" # Config
+
+log = "0.4.17" # Logging
+simple_logger = "4.1.0" # Logging
+
+diesel = { version = "2.0.0", features = ["postgres", "r2d2"] } # Database
+dotenvy = "0.15" # Database
+diesel_migrations = "2.0.0" # Database
+r2d2 = "0.8.10" # Database
\ No newline at end of file
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..3c284bb
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("cargo:rerun-if-changed=migrations/");
+}
\ No newline at end of file
diff --git a/diesel.toml b/diesel.toml
new file mode 100644
index 0000000..35a12ff
--- /dev/null
+++ b/diesel.toml
@@ -0,0 +1,8 @@
+# For documentation on how to configure this file,
+# see https://diesel.rs/guides/configuring-diesel-cli
+
+[print_schema]
+file = "src/schema.rs"
+
+[migrations_directory]
+dir = "migrations"
diff --git a/migrations/.keep b/migrations/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/migrations/00000000000000_diesel_initial_setup/down.sql b/migrations/00000000000000_diesel_initial_setup/down.sql
new file mode 100644
index 0000000..a9f5260
--- /dev/null
+++ b/migrations/00000000000000_diesel_initial_setup/down.sql
@@ -0,0 +1,6 @@
+-- This file was automatically created by Diesel to setup helper functions
+-- and other internal bookkeeping. This file is safe to edit, any future
+-- changes will be added to existing projects as new migrations.
+
+DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
+DROP FUNCTION IF EXISTS diesel_set_updated_at();
diff --git a/migrations/00000000000000_diesel_initial_setup/up.sql b/migrations/00000000000000_diesel_initial_setup/up.sql
new file mode 100644
index 0000000..d68895b
--- /dev/null
+++ b/migrations/00000000000000_diesel_initial_setup/up.sql
@@ -0,0 +1,36 @@
+-- This file was automatically created by Diesel to setup helper functions
+-- and other internal bookkeeping. This file is safe to edit, any future
+-- changes will be added to existing projects as new migrations.
+
+
+
+
+-- Sets up a trigger for the given table to automatically set a column called
+-- `updated_at` whenever the row is modified (unless `updated_at` was included
+-- in the modified columns)
+--
+-- # Example
+--
+-- ```sql
+-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
+--
+-- SELECT diesel_manage_updated_at('users');
+-- ```
+CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
+BEGIN
+ EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
+ FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
+BEGIN
+ IF (
+ NEW IS DISTINCT FROM OLD AND
+ NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
+ ) THEN
+ NEW.updated_at := current_timestamp;
+ END IF;
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
diff --git a/migrations/2023-03-26-024321_create_users/down.sql b/migrations/2023-03-26-024321_create_users/down.sql
new file mode 100644
index 0000000..441087a
--- /dev/null
+++ b/migrations/2023-03-26-024321_create_users/down.sql
@@ -0,0 +1 @@
+DROP TABLE users;
\ No newline at end of file
diff --git a/migrations/2023-03-26-024321_create_users/up.sql b/migrations/2023-03-26-024321_create_users/up.sql
new file mode 100644
index 0000000..5beeeb9
--- /dev/null
+++ b/migrations/2023-03-26-024321_create_users/up.sql
@@ -0,0 +1,5 @@
+CREATE TABLE users (
+ id SERIAL NOT NULL PRIMARY KEY,
+ name VARCHAR(128) NOT NULL UNIQUE,
+ discord_id BIGINT NOT NULL UNIQUE
+);
\ No newline at end of file
diff --git a/migrations/2023-03-26-024710_create_3fa_codes/down.sql b/migrations/2023-03-26-024710_create_3fa_codes/down.sql
new file mode 100644
index 0000000..fcf38e1
--- /dev/null
+++ b/migrations/2023-03-26-024710_create_3fa_codes/down.sql
@@ -0,0 +1 @@
+DROP TABLE codes_3fa;
\ No newline at end of file
diff --git a/migrations/2023-03-26-024710_create_3fa_codes/up.sql b/migrations/2023-03-26-024710_create_3fa_codes/up.sql
new file mode 100644
index 0000000..94a5539
--- /dev/null
+++ b/migrations/2023-03-26-024710_create_3fa_codes/up.sql
@@ -0,0 +1,6 @@
+CREATE TABLE codes_3fa (
+ id SERIAL NOT NULL PRIMARY KEY,
+ code VARCHAR(10) NOT NULL UNIQUE,
+ user_id SERIAL NOT NULL REFERENCES users(id),
+ expires_on BIGINT NOT NULL
+);
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 23e91d0..72086cd 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,12 +1,20 @@
use actix_web::{App, HttpResponse, HttpServer, web, get, post, Responder, HttpRequest};
use actix_web::web::{Data, Json, JsonConfig};
-use log::{error, Level};
+use diesel::{Connection, PgConnection};
+use diesel::r2d2::ConnectionManager;
+use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
+use log::{error, info, Level};
+use r2d2::Pool;
use serde::{Serialize, Deserialize};
use crate::config::CONFIG;
use crate::error::{APIError, APIErrorResponse};
pub mod config;
pub mod error;
+pub mod models;
+pub mod schema;
+
+pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
#[derive(Serialize, Deserialize)]
pub struct CodeRequest3FA {
@@ -27,15 +35,51 @@ pub async fn get_3fa_code(req: Json) -> HttpResponse {
})
}
+
+
HttpResponse::Ok().body("d")
}
+pub type PgPool = Pool>;
+
#[actix_web::main]
async fn main() -> std::io::Result<()> {
simple_logger::init_with_level(Level::Debug).unwrap();
+ info!("Connecting to database...");
+
+ let mut manager = ConnectionManager::new(&CONFIG.db_uri);
+ let mut pool: PgPool = match Pool::builder().build(manager) {
+ Ok(c) => c,
+ Err(e) => {
+ error!("Error connecting to database: {}", e);
+ std::process::exit(1);
+ }
+ };
+
+ let mut conn = match pool.get() {
+ Ok(c) => c,
+ Err(e) => {
+ error!("Error fetching connection: {}", e);
+ std::process::exit(1);
+ }
+ };
+
+ let data = Data::new(pool);
+
+ info!("Running migrations...");
+
+ match conn.run_pending_migrations(MIGRATIONS) {
+ Ok(_) => (),
+ Err(e) => {
+ error!("Error running database migrations: {}", e);
+ std::process::exit(1);
+ }
+ };
+
HttpServer::new(move || {
App::new()
+ .app_data(data.clone())
.app_data(JsonConfig::default().error_handler(|err, req| {
let err2: APIError = (&err).into();
actix_web::error::InternalError::from_response(
diff --git a/src/models.rs b/src/models.rs
new file mode 100644
index 0000000..85cc434
--- /dev/null
+++ b/src/models.rs
@@ -0,0 +1,19 @@
+use diesel::prelude::*;
+
+#[derive(Queryable)]
+#[diesel(table_name = users)]
+pub struct User {
+ pub id: i32,
+ pub name: String,
+ pub discord_id: i64
+}
+
+#[derive(Queryable)]
+#[diesel(table_name = codes_3fa)]
+#[diesel(belongs_to(User))]
+pub struct Code3FA {
+ pub id: i32,
+ pub code: String,
+ pub user_id: i32,
+ pub expires_on: i64
+}
\ No newline at end of file
diff --git a/src/schema.rs b/src/schema.rs
new file mode 100644
index 0000000..d8ee678
--- /dev/null
+++ b/src/schema.rs
@@ -0,0 +1,25 @@
+// @generated automatically by Diesel CLI.
+
+diesel::table! {
+ codes_3fa (id) {
+ id -> Int4,
+ code -> Varchar,
+ user_id -> Int4,
+ expires_on -> Int8,
+ }
+}
+
+diesel::table! {
+ users (id) {
+ id -> Int4,
+ name -> Varchar,
+ discord_id -> Int8,
+ }
+}
+
+diesel::joinable!(codes_3fa -> users (user_id));
+
+diesel::allow_tables_to_appear_in_same_query!(
+ codes_3fa,
+ users,
+);