From 817c742d09dda6c08a0552ed4a39d00025b2816c Mon Sep 17 00:00:00 2001 From: mvvasilev Date: Thu, 11 Jan 2024 14:26:34 +0200 Subject: [PATCH] Add Dockerfile --- ...e9b2a8409e92eebee83150ee8f57fa20728f4.json | 64 ++++++++++ ...4418eeb22faa0bc9cb7e2877a1407a242afe0.json | 27 +++++ ...b5817581f05528ced1856b2a974e7767b8af7.json | 28 +++++ ...1b7289f16549b24aeb49af2632f3c743a5076.json | 58 ++++++++++ ...867ebeaf9a921f0e95e8ade09f14899409c58.json | 64 ++++++++++ ...38e835447bd3478ec50245eca833e476fd9bf.json | 58 ++++++++++ Cargo.lock | 109 ++++++++++++++++++ Cargo.toml | 1 + Dockerfile | 62 ++++++++++ README.md | 15 +++ .../20240111111901_ChangeIpColumnSize.sql | 2 + src/endpoints.rs | 2 +- src/main.rs | 8 ++ 13 files changed, 497 insertions(+), 1 deletion(-) create mode 100644 .sqlx/query-1db35e76adcb0ed4de84b8296efe9b2a8409e92eebee83150ee8f57fa20728f4.json create mode 100644 .sqlx/query-2aac7a200b3c65e8d406e4844c14418eeb22faa0bc9cb7e2877a1407a242afe0.json create mode 100644 .sqlx/query-4437b6962ab26de280e4aecc39db5817581f05528ced1856b2a974e7767b8af7.json create mode 100644 .sqlx/query-44fb63d566bb22d02ef6a0583fc1b7289f16549b24aeb49af2632f3c743a5076.json create mode 100644 .sqlx/query-761513e437e36f444040e6f375e867ebeaf9a921f0e95e8ade09f14899409c58.json create mode 100644 .sqlx/query-d13c89523084d914be6e6250b2738e835447bd3478ec50245eca833e476fd9bf.json create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 migrations/20240111111901_ChangeIpColumnSize.sql diff --git a/.sqlx/query-1db35e76adcb0ed4de84b8296efe9b2a8409e92eebee83150ee8f57fa20728f4.json b/.sqlx/query-1db35e76adcb0ed4de84b8296efe9b2a8409e92eebee83150ee8f57fa20728f4.json new file mode 100644 index 0000000..70ecda1 --- /dev/null +++ b/.sqlx/query-1db35e76adcb0ed4de84b8296efe9b2a8409e92eebee83150ee8f57fa20728f4.json @@ -0,0 +1,64 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT * FROM events.event\n WHERE id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "event_type", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "description", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "snowflake_id", + "type_info": "Varchar" + }, + { + "ordinal": 5, + "name": "from_date", + "type_info": "Timestamp" + }, + { + "ordinal": 6, + "name": "to_date", + "type_info": "Timestamp" + }, + { + "ordinal": 7, + "name": "duration", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + true, + false, + true, + true, + false + ] + }, + "hash": "1db35e76adcb0ed4de84b8296efe9b2a8409e92eebee83150ee8f57fa20728f4" +} diff --git a/.sqlx/query-2aac7a200b3c65e8d406e4844c14418eeb22faa0bc9cb7e2877a1407a242afe0.json b/.sqlx/query-2aac7a200b3c65e8d406e4844c14418eeb22faa0bc9cb7e2877a1407a242afe0.json new file mode 100644 index 0000000..c2f41cb --- /dev/null +++ b/.sqlx/query-2aac7a200b3c65e8d406e4844c14418eeb22faa0bc9cb7e2877a1407a242afe0.json @@ -0,0 +1,27 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO events.availability (event_id, from_date, to_date, user_email, user_ip, user_name)\n VALUES ($1, $2, $3, $4, $5, $6)\n RETURNING id\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8", + "Timestamp", + "Timestamp", + "Varchar", + "Varchar", + "Varchar" + ] + }, + "nullable": [ + false + ] + }, + "hash": "2aac7a200b3c65e8d406e4844c14418eeb22faa0bc9cb7e2877a1407a242afe0" +} diff --git a/.sqlx/query-4437b6962ab26de280e4aecc39db5817581f05528ced1856b2a974e7767b8af7.json b/.sqlx/query-4437b6962ab26de280e4aecc39db5817581f05528ced1856b2a974e7767b8af7.json new file mode 100644 index 0000000..d77e1d1 --- /dev/null +++ b/.sqlx/query-4437b6962ab26de280e4aecc39db5817581f05528ced1856b2a974e7767b8af7.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO events.event (snowflake_id, name, description, from_date, to_date, event_type, duration)\n VALUES ($1, $2, $3, $4, $5, $6, $7)\n RETURNING id\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Varchar", + "Varchar", + "Varchar", + "Timestamp", + "Timestamp", + "Varchar", + "Int4" + ] + }, + "nullable": [ + false + ] + }, + "hash": "4437b6962ab26de280e4aecc39db5817581f05528ced1856b2a974e7767b8af7" +} diff --git a/.sqlx/query-44fb63d566bb22d02ef6a0583fc1b7289f16549b24aeb49af2632f3c743a5076.json b/.sqlx/query-44fb63d566bb22d02ef6a0583fc1b7289f16549b24aeb49af2632f3c743a5076.json new file mode 100644 index 0000000..1ba0542 --- /dev/null +++ b/.sqlx/query-44fb63d566bb22d02ef6a0583fc1b7289f16549b24aeb49af2632f3c743a5076.json @@ -0,0 +1,58 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT a.*\n FROM events.availability AS a\n JOIN events.event AS e ON e.id = a.event_id\n WHERE e.snowflake_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "event_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "from_date", + "type_info": "Timestamp" + }, + { + "ordinal": 3, + "name": "to_date", + "type_info": "Timestamp" + }, + { + "ordinal": 4, + "name": "user_email", + "type_info": "Varchar" + }, + { + "ordinal": 5, + "name": "user_name", + "type_info": "Varchar" + }, + { + "ordinal": 6, + "name": "user_ip", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false, + true, + false, + false + ] + }, + "hash": "44fb63d566bb22d02ef6a0583fc1b7289f16549b24aeb49af2632f3c743a5076" +} diff --git a/.sqlx/query-761513e437e36f444040e6f375e867ebeaf9a921f0e95e8ade09f14899409c58.json b/.sqlx/query-761513e437e36f444040e6f375e867ebeaf9a921f0e95e8ade09f14899409c58.json new file mode 100644 index 0000000..2bb1c3e --- /dev/null +++ b/.sqlx/query-761513e437e36f444040e6f375e867ebeaf9a921f0e95e8ade09f14899409c58.json @@ -0,0 +1,64 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT * FROM events.event\n WHERE snowflake_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "event_type", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "description", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "snowflake_id", + "type_info": "Varchar" + }, + { + "ordinal": 5, + "name": "from_date", + "type_info": "Timestamp" + }, + { + "ordinal": 6, + "name": "to_date", + "type_info": "Timestamp" + }, + { + "ordinal": 7, + "name": "duration", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + true, + false, + true, + true, + false + ] + }, + "hash": "761513e437e36f444040e6f375e867ebeaf9a921f0e95e8ade09f14899409c58" +} diff --git a/.sqlx/query-d13c89523084d914be6e6250b2738e835447bd3478ec50245eca833e476fd9bf.json b/.sqlx/query-d13c89523084d914be6e6250b2738e835447bd3478ec50245eca833e476fd9bf.json new file mode 100644 index 0000000..f73c312 --- /dev/null +++ b/.sqlx/query-d13c89523084d914be6e6250b2738e835447bd3478ec50245eca833e476fd9bf.json @@ -0,0 +1,58 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT *\n FROM events.availability\n WHERE event_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "event_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "from_date", + "type_info": "Timestamp" + }, + { + "ordinal": 3, + "name": "to_date", + "type_info": "Timestamp" + }, + { + "ordinal": 4, + "name": "user_email", + "type_info": "Varchar" + }, + { + "ordinal": 5, + "name": "user_name", + "type_info": "Varchar" + }, + { + "ordinal": 6, + "name": "user_ip", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + true, + false, + false + ] + }, + "hash": "d13c89523084d914be6e6250b2738e835447bd3478ec50245eca833e476fd9bf" +} diff --git a/Cargo.lock b/Cargo.lock index 5cd1f4b..8344950 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,6 +30,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + [[package]] name = "allocator-api2" version = "0.2.16" @@ -363,6 +372,19 @@ dependencies = [ "serde", ] +[[package]] +name = "env_logger" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -409,6 +431,7 @@ dependencies = [ "axum", "chrono", "dotenv", + "env_logger", "futures", "rand", "serde", @@ -715,6 +738,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "1.1.0" @@ -795,6 +824,17 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "is-terminal" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "itertools" version = "0.12.0" @@ -1197,6 +1237,35 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "rsa" version = "0.9.6" @@ -1659,6 +1728,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.56" @@ -1975,6 +2053,37 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 2bb34e9..44916d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" axum = { version = "0.7.3", features = ["macros", "tokio"] } chrono = { version = "0.4.31", features = ["serde"] } dotenv = "0.15.0" +env_logger = "0.10.1" futures = "0.3.30" rand = "0.8.5" serde = { version = "1.0.195", features = ["derive"] } diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d0f4de1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,62 @@ +### Build Back-End ### + +FROM rust:1.73-slim-buster as rustbuild + +WORKDIR /findtheti-me + +COPY ./Cargo.lock ./Cargo.lock +COPY ./Cargo.toml ./Cargo.toml +COPY ./src ./src +COPY ./.sqlx ./.sqlx +COPY ./migrations ./migrations + +RUN cargo build --release + +### Build Front-End ### + +FROM node:lts as nodebuilder + +WORKDIR /app + +COPY ./frontend/package*.json ./ +COPY ./frontend/tsconfig*.json ./ + +RUN yarn install --prefer-offline --frozen-lockfile --non-interactive --production=true + +COPY ./frontend ./ + +RUN yarn build + +RUN rm -rf node_modules + +### Combine Both Into Running Image ### + +FROM rust:1.73-slim-buster + +RUN adduser \ + --disabled-password \ + --gecos "" \ + --home "/nonexistent" \ + --shell "/sbin/nologin" \ + --no-create-home \ + --uid "10001" \ + appuser + +COPY --from=rustbuild /findtheti-me/target/release/findtheti-me ./findtheti-me/ + +RUN chown appuser ./findtheti-me/findtheti-me + +COPY --from=nodebuilder /app/dist ./findtheti-me/frontend/dist + +RUN chown -R appuser ./findtheti-me + +USER appuser + +ENV RUST_LOG="findtheti-me=debug,info" +ENV EVENT_UID_SIZE=20 + +WORKDIR ./findtheti-me + +ENTRYPOINT ["./findtheti-me"] + +EXPOSE 8080/tcp \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3449db6 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Setup For Development +## Backend +1. Create a PostgreSQL database +2. Configure a `.env` in the project root directory ( following `.env.example` ) +3. Run `cargo sqlx migrate run` to run all migrations ( ensure you've created the database beforehand ) +4. `cargo run` + +## Frontend +1. `yarn install` +2. `yarn dev` ( or `yarn build`/`yarn preview` ) + +## Docker Build Image +1. Do Backend and Frontend setups first +2. Run `cargo sqlx prepare` ( ensure .sqlx directory has been created. The one included in this git repo may be out of date. ) +3. `docker build .` ( or `podman build .` ) in root directory \ No newline at end of file diff --git a/migrations/20240111111901_ChangeIpColumnSize.sql b/migrations/20240111111901_ChangeIpColumnSize.sql new file mode 100644 index 0000000..3aec03e --- /dev/null +++ b/migrations/20240111111901_ChangeIpColumnSize.sql @@ -0,0 +1,2 @@ +ALTER TABLE events.availability +ALTER COLUMN user_ip TYPE VARCHAR(15); \ No newline at end of file diff --git a/src/endpoints.rs b/src/endpoints.rs index 3d34020..64d4e9f 100644 --- a/src/endpoints.rs +++ b/src/endpoints.rs @@ -2,7 +2,7 @@ use std::net::SocketAddr; use axum::{ extract::{Path, State, ConnectInfo}, - Json, http::StatusCode, Extension, + Json, http::StatusCode, }; use chrono::{DateTime, TimeZone, Utc}; use rand::{distributions::Alphanumeric, Rng}; diff --git a/src/main.rs b/src/main.rs index 89070d0..9bb6e46 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,8 @@ mod entity; #[tokio::main(flavor = "multi_thread")] async fn main() { + println!("Starting findtheti.me..."); + dotenv().ok(); let api_routes = api::routes().await.expect("Unable to create api routes"); @@ -22,14 +24,20 @@ async fn main() { // If in release mod, serve static files if !cfg!(debug_assertions) { + println!("Initializing frontend routes..."); + routes = routes.nest_service("/", ServeDir::new("./frontend/dist")) .fallback_service(ServeDir::new("./frontend/dist")); } + println!("Routes initialized..."); + let addr = SocketAddr::from(([127, 0, 0, 1], 8080)); let listener = TcpListener::bind(addr).await.unwrap(); + println!("Starting server..."); + axum::serve(listener, routes.into_make_service_with_connect_info::()) .await .unwrap();