Compare commits

..
Author SHA1 Message Date
phoenix 453830b208 Updating name (#4)
Release Tagging / release (push) Failing after 1m40s
soaricarus_auth Build / Rustfmt (push) Successful in 52s
soaricarus_auth Build / Check (push) Successful in 2m5s
soaricarus_auth Build / Clippy (push) Successful in 2m48s
soaricarus_auth Build / build (push) Successful in 3m12s
soaricarus_auth Build / Test Suite (push) Successful in 4m35s
Reviewed-on: #4
2026-07-21 15:29:23 -04:00
phoenix 2d376524eb Update postgres (#3)
Release Tagging / release (push) Failing after 56s
icarus_auth Build / Check (push) Successful in 2m2s
icarus_auth Build / Test Suite (push) Successful in 2m19s
icarus_auth Build / Rustfmt (push) Successful in 32s
icarus_auth Build / build (push) Successful in 1m44s
icarus_auth Build / Clippy (push) Successful in 2m25s
Reviewed-on: phoenix/icarus_auth#3
2026-07-09 10:35:55 -04:00
phoenix e518b1e096 Update (#2)
Release Tagging / release (push) Successful in 49s
Rust Build / Check (push) Successful in 1m39s
Rust Build / Test Suite (push) Successful in 2m1s
Rust Build / Rustfmt (push) Successful in 1m43s
Rust Build / Clippy (push) Successful in 1m34s
Rust Build / build (push) Successful in 3m17s
Reviewed-on: phoenix/icarus_auth#2
2026-07-07 17:35:28 -04:00
16 changed files with 430 additions and 856 deletions
+4 -3
View File
@@ -5,9 +5,10 @@ RUST_LOG=debug
ALLOWED_ORIGINS=https://soaricarus.com,https://www.soaricarus.com ALLOWED_ORIGINS=https://soaricarus.com,https://www.soaricarus.com
SECRET_KEY=refero34o8rfhfjn983thf39fhc943rf923n3h SECRET_KEY=refero34o8rfhfjn983thf39fhc943rf923n3h
SERVICE_PASSPHRASE=iUOo1fxshf3y1tUGn1yU8l9raPApHCdinW0VdCHdRFEjqhR3Bf02aZzsKbLtaDFH SERVICE_PASSPHRASE=iUOo1fxshf3y1tUGn1yU8l9raPApHCdinW0VdCHdRFEjqhR3Bf02aZzsKbLtaDFH
POSTGRES_AUTH_USER=icarus_op POSTGRES_AUTH_USER=soaricarus_op
POSTGRES_AUTH_PASSWORD=password POSTGRES_AUTH_PASSWORD=password
POSTGRES_AUTH_DB=icarus_auth_db POSTGRES_AUTH_DB=soaricarus_auth_db
POSTGRES_AUTH_HOST=auth_db POSTGRES_AUTH_HOST=auth_db
DATABASE_URL=postgresql://${POSTGRES_AUTH_USER}:${POSTGRES_AUTH_PASSWORD}@${POSTGRES_AUTH_HOST}:5432/${POSTGRES_AUTH_DB} POSTGRES_AUTH_PORT=5432
DATABASE_URL=postgresql://${POSTGRES_AUTH_USER}:${POSTGRES_AUTH_PASSWORD}@${POSTGRES_AUTH_HOST}:${POSTGRES_AUTH_PORT}/${POSTGRES_AUTH_DB}
ENABLE_REGISTRATION=TRUE ENABLE_REGISTRATION=TRUE
+4 -3
View File
@@ -5,9 +5,10 @@ RUST_LOG=debug
ALLOWED_ORIGINS=https://soaricarus.com,https://www.soaricarus.com ALLOWED_ORIGINS=https://soaricarus.com,https://www.soaricarus.com
SECRET_KEY=refero34o8rfhfjn983thf39fhc943rf923n3h SECRET_KEY=refero34o8rfhfjn983thf39fhc943rf923n3h
SERVICE_PASSPHRASE=iUOo1fxshf3y1tUGn1yU8l9raPApHCdinW0VdCHdRFEjqhR3Bf02aZzsKbLtaDFH SERVICE_PASSPHRASE=iUOo1fxshf3y1tUGn1yU8l9raPApHCdinW0VdCHdRFEjqhR3Bf02aZzsKbLtaDFH
POSTGRES_AUTH_USER=icarus_op_test POSTGRES_AUTH_USER=soaricarus_op_test
POSTGRES_AUTH_PASSWORD=password POSTGRES_AUTH_PASSWORD=password
POSTGRES_AUTH_DB=icarus_auth_test_db POSTGRES_AUTH_DB=soaricarus_auth_test_db
POSTGRES_AUTH_HOST=localhost POSTGRES_AUTH_HOST=localhost
DATABASE_URL=postgresql://${POSTGRES_AUTH_USER}:${POSTGRES_AUTH_PASSWORD}@${POSTGRES_AUTH_HOST}:5432/${POSTGRES_AUTH_DB} POSTGRES_AUTH_PORT=5432
DATABASE_URL=postgresql://${POSTGRES_AUTH_USER}:${POSTGRES_AUTH_PASSWORD}@${POSTGRES_AUTH_HOST}:${POSTGRES_AUTH_PORT}/${POSTGRES_AUTH_DB}
ENABLE_REGISTRATION=TRUE ENABLE_REGISTRATION=TRUE
+4 -3
View File
@@ -10,15 +10,16 @@ jobs:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
fetch-depth: 0 # Important for git describe --tags fetch-depth: 0
- name: Install Rust - name: Install Rust
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
toolchain: 1.95 toolchain: 1.97
components: cargo components: cargo
- uses: Swatinem/rust-cache@v2
- name: Extract Version from Cargo.toml - name: Extract Version from Cargo.toml
id: version id: version
+32 -36
View File
@@ -1,48 +1,44 @@
name: Rust Build name: soaricarus_auth Build
on: on:
push: push:
branches: branches:
- main - main
- devel
pull_request: pull_request:
branches: branches:
- main - main
- devel
jobs: jobs:
check: check:
name: Check name: Check
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions-rust-lang/setup-rust-toolchain@v1 - uses: actions-rust-lang/setup-rust-toolchain@v1
with: with:
toolchain: 1.95 toolchain: 1.97
- uses: Swatinem/rust-cache@v2
- run: | - run: |
mkdir -p ~/.ssh mkdir -p ~/.ssh
echo "${{ secrets.MYREPO_TOKEN }}" > ~/.ssh/icarus_models_deploy_key echo "${{ secrets.MYREPO_TOKEN }}" > ~/.ssh/soaricarus_models_deploy_key
chmod 600 ~/.ssh/icarus_models_deploy_key chmod 600 ~/.ssh/soaricarus_models_deploy_key
ssh-keyscan ${{ vars.MYHOST }} >> ~/.ssh/known_hosts ssh-keyscan ${{ vars.MYHOST }} >> ~/.ssh/known_hosts
eval $(ssh-agent -s) eval $(ssh-agent -s)
ssh-add -v ~/.ssh/icarus_models_deploy_key ssh-add -v ~/.ssh/soaricarus_models_deploy_key
cargo check cargo check
test: test:
name: Test Suite name: Test Suite
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
# --- Add database service definition ---
services: services:
postgres: postgres:
image: postgres:18.3-alpine image: postgres:18.4-alpine
env: env:
# Use secrets for DB init, with fallbacks for flexibility
POSTGRES_USER: ${{ secrets.DB_TEST_USER || 'testuser' }} POSTGRES_USER: ${{ secrets.DB_TEST_USER || 'testuser' }}
POSTGRES_PASSWORD: ${{ secrets.DB_TEST_PASSWORD || 'testpassword' }} POSTGRES_PASSWORD: ${{ secrets.DB_TEST_PASSWORD || 'testpassword' }}
POSTGRES_DB: ${{ secrets.DB_TEST_NAME || 'testdb' }} POSTGRES_DB: ${{ secrets.DB_TEST_NAME || 'testdb' }}
# Options to wait until the database is ready
options: >- options: >-
--health-cmd pg_isready --health-cmd pg_isready
--health-interval 10s --health-interval 10s
@@ -50,11 +46,11 @@ jobs:
--health-retries 5 --health-retries 5
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions-rust-lang/setup-rust-toolchain@v1 - uses: actions-rust-lang/setup-rust-toolchain@v1
with: with:
toolchain: 1.95 toolchain: 1.97
# --- Add this step for explicit verification --- - uses: Swatinem/rust-cache@v2
- name: Verify Docker Environment - name: Verify Docker Environment
run: | run: |
echo "Runner User Info:" echo "Runner User Info:"
@@ -66,25 +62,22 @@ jobs:
echo "Checking Docker Daemon Status (ps):" echo "Checking Docker Daemon Status (ps):"
docker ps -a docker ps -a
echo "Docker environment check complete." echo "Docker environment check complete."
# NOTE: Do NOT use continue-on-error here.
# If Docker isn't working as expected, the job SHOULD fail here.
- name: Run tests - name: Run tests
env: env:
# Define DATABASE_URL for tests to use # Define DATABASE_URL for tests to use
DATABASE_URL: postgresql://${{ secrets.DB_TEST_USER || 'testuser' }}:${{ secrets.DB_TEST_PASSWORD || 'testpassword' }}@postgres:5432/${{ secrets.DB_TEST_NAME || 'testdb' }} DATABASE_URL: postgresql://${{ secrets.DB_TEST_USER || 'testuser' }}:${{ secrets.DB_TEST_PASSWORD || 'testpassword' }}@postgres:5432/${{ secrets.DB_TEST_NAME || 'testdb' }}
RUST_LOG: info # Optional: configure test log level RUST_LOG: info # Optional: configure test log level
SECRET_KEY: ${{ secrets.TOKEN_SECRET_KEY }} SECRET_KEY: ${{ secrets.TOKEN_SECRET_KEY }}
# Make SSH agent available if tests fetch private dependencies
SSH_AUTH_SOCK: ${{ env.SSH_AUTH_SOCK }} SSH_AUTH_SOCK: ${{ env.SSH_AUTH_SOCK }}
ENABLE_REGISTRATION: 'TRUE' ENABLE_REGISTRATION: 'TRUE'
run: | run: |
mkdir -p ~/.ssh mkdir -p ~/.ssh
echo "${{ secrets.MYREPO_TOKEN }}" > ~/.ssh/icarus_models_deploy_key echo "${{ secrets.MYREPO_TOKEN }}" > ~/.ssh/soaricarus_models_deploy_key
chmod 600 ~/.ssh/icarus_models_deploy_key chmod 600 ~/.ssh/soaricarus_models_deploy_key
ssh-keyscan ${{ vars.MYHOST }} >> ~/.ssh/known_hosts ssh-keyscan ${{ vars.MYHOST }} >> ~/.ssh/known_hosts
eval $(ssh-agent -s) eval $(ssh-agent -s)
ssh-add -v ~/.ssh/icarus_models_deploy_key ssh-add -v ~/.ssh/soaricarus_models_deploy_key
cargo test cargo test
@@ -92,54 +85,57 @@ jobs:
name: Rustfmt name: Rustfmt
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions-rust-lang/setup-rust-toolchain@v1 - uses: actions-rust-lang/setup-rust-toolchain@v1
with: with:
toolchain: 1.95 toolchain: 1.97
- uses: Swatinem/rust-cache@v2
- run: rustup component add rustfmt - run: rustup component add rustfmt
- run: | - run: |
mkdir -p ~/.ssh mkdir -p ~/.ssh
echo "${{ secrets.MYREPO_TOKEN }}" > ~/.ssh/icarus_models_deploy_key echo "${{ secrets.MYREPO_TOKEN }}" > ~/.ssh/soaricarus_models_deploy_key
chmod 600 ~/.ssh/icarus_models_deploy_key chmod 600 ~/.ssh/soaricarus_models_deploy_key
ssh-keyscan ${{ vars.MYHOST }} >> ~/.ssh/known_hosts ssh-keyscan ${{ vars.MYHOST }} >> ~/.ssh/known_hosts
eval $(ssh-agent -s) eval $(ssh-agent -s)
ssh-add -v ~/.ssh/icarus_models_deploy_key ssh-add -v ~/.ssh/soaricarus_models_deploy_key
cargo fmt --all -- --check cargo fmt --all -- --check
clippy: clippy:
name: Clippy name: Clippy
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions-rust-lang/setup-rust-toolchain@v1 - uses: actions-rust-lang/setup-rust-toolchain@v1
with: with:
toolchain: 1.95 toolchain: 1.97
- uses: Swatinem/rust-cache@v2
- run: rustup component add clippy - run: rustup component add clippy
- run: | - run: |
mkdir -p ~/.ssh mkdir -p ~/.ssh
echo "${{ secrets.MYREPO_TOKEN }}" > ~/.ssh/icarus_models_deploy_key echo "${{ secrets.MYREPO_TOKEN }}" > ~/.ssh/soaricarus_models_deploy_key
chmod 600 ~/.ssh/icarus_models_deploy_key chmod 600 ~/.ssh/soaricarus_models_deploy_key
ssh-keyscan ${{ vars.MYHOST }} >> ~/.ssh/known_hosts ssh-keyscan ${{ vars.MYHOST }} >> ~/.ssh/known_hosts
eval $(ssh-agent -s) eval $(ssh-agent -s)
ssh-add -v ~/.ssh/icarus_models_deploy_key ssh-add -v ~/.ssh/soaricarus_models_deploy_key
cargo clippy -- -D warnings cargo clippy -- -D warnings
build: build:
name: build name: build
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions-rust-lang/setup-rust-toolchain@v1 - uses: actions-rust-lang/setup-rust-toolchain@v1
with: with:
toolchain: 1.95 toolchain: 1.97
- uses: Swatinem/rust-cache@v2
- run: | - run: |
mkdir -p ~/.ssh mkdir -p ~/.ssh
echo "${{ secrets.MYREPO_TOKEN }}" > ~/.ssh/icarus_models_deploy_key echo "${{ secrets.MYREPO_TOKEN }}" > ~/.ssh/soaricarus_models_deploy_key
chmod 600 ~/.ssh/icarus_models_deploy_key chmod 600 ~/.ssh/soaricarus_models_deploy_key
ssh-keyscan ${{ vars.MYHOST }} >> ~/.ssh/known_hosts ssh-keyscan ${{ vars.MYHOST }} >> ~/.ssh/known_hosts
eval $(ssh-agent -s) eval $(ssh-agent -s)
ssh-add -v ~/.ssh/icarus_models_deploy_key ssh-add -v ~/.ssh/soaricarus_models_deploy_key
cargo build --release cargo build --release
Generated
+282 -708
View File
File diff suppressed because it is too large Load Diff
+14 -14
View File
@@ -1,30 +1,30 @@
[package] [package]
name = "icarus_auth" name = "soaricarus_auth"
version = "0.8.0" version = "0.8.1"
edition = "2024" edition = "2024"
rust-version = "1.95" rust-version = "1.95"
license = "MIT"
description = "Auth API for soaricarus"
[dependencies] [dependencies]
axum = { version = "0.8.9" } axum = { version = "0.8.9" }
openssl = { version = "0.10.81", features = ["vendored"] }
serde = { version = "1.0.228", features = ["derive"] } serde = { version = "1.0.228", features = ["derive"] }
serde_json = { version = "1.0.149" } serde_json = { version = "1.0.150" }
tokio = { version = "1.52.2", features = ["rt-multi-thread"] } tokio = { version = "1.52.3", features = ["rt-multi-thread"] }
tracing-subscriber = { version = "0.3.23" } tracing-subscriber = { version = "0.3.23" }
tower = { version = "0.5.3", features = ["full"] } tower = { version = "0.5.3", features = ["full"] }
tower-http = { version = "0.6.10", features = ["cors"] } tower-http = { version = "0.7.0", features = ["cors"] }
hyper = { version = "1.9.0" } sqlx = { version = "0.9.0", features = ["postgres", "runtime-tokio", "tls-native-tls", "time", "uuid"] }
sqlx = { version = "0.8.6", features = ["postgres", "runtime-tokio-native-tls", "time", "uuid"] } uuid = { version = "1.23.5", features = ["v4", "serde"] }
uuid = { version = "1.23.1", features = ["v4", "serde"] } argon2 = { version = "0.5.3", features = ["std"] }
argon2 = { version = "0.5.3", features = ["std"] } # Use the latest 0.5.x version time = { version = "0.3.53", features = ["macros", "serde"] }
rand = { version = "0.10.1" }
time = { version = "0.3.47", features = ["macros", "serde"] }
josekit = { version = "0.10.3" } josekit = { version = "0.10.3" }
utoipa = { version = "5.5.0", features = ["axum_extras"] } utoipa = { version = "5.5.0", features = ["axum_extras"] }
utoipa-swagger-ui = { version = "9.0.2", features = ["axum"] } utoipa-swagger-ui = { version = "9.0.2", features = ["axum"] }
icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.11.1" } simodels = { git = "ssh://git@git.kundeng.us/phoenix/simodels.git", tag = "v0.11.3-main-fe9d101bd0-111" }
icarus_envy = { git = "ssh://git@git.kundeng.us/phoenix/icarus_envy.git", tag = "v0.7.0" } sienvy = { git = "ssh://git@git.kundeng.us/phoenix/sienvy.git", tag = "v0.8.0-main-d06c8fdf49-006" }
[dev-dependencies] [dev-dependencies]
http-body-util = { version = "0.1.3" } http-body-util = { version = "0.1.3" }
url = { version = "2.5.8" } url = { version = "2.5.8" }
once_cell = { version = "1.21.4" } # Useful for lazy initialization in tests/app setup
+4 -23
View File
@@ -1,14 +1,8 @@
# Stage 1: Build the application FROM rust:1.97 as builder
# Use a specific Rust version for reproducibility. Choose one that matches your development environment.
# Using slim variant for smaller base image
FROM rust:1.95 as builder
# Set the working directory inside the container # Set the working directory inside the container
WORKDIR /usr/src/app WORKDIR /usr/src/app
# Install build dependencies if needed (e.g., for certain crates like sqlx with native TLS)
# RUN apt-get update && apt-get install -y pkg-config libssl-dev
# Install build dependencies if needed (e.g., git for cloning) # Install build dependencies if needed (e.g., git for cloning)
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config libssl3 \ pkg-config libssl3 \
@@ -16,36 +10,25 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
openssh-client git \ openssh-client git \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# << --- ADD HOST KEY HERE --- >>
# Replace 'yourgithost.com' with the actual hostname (e.g., github.com)
RUN mkdir -p -m 0700 ~/.ssh && \ RUN mkdir -p -m 0700 ~/.ssh && \
ssh-keyscan git.kundeng.us >> ~/.ssh/known_hosts ssh-keyscan git.kundeng.us >> ~/.ssh/known_hosts
# Copy Cargo manifests # Copy Cargo manifests
COPY Cargo.toml Cargo.lock ./ COPY Cargo.toml Cargo.lock ./
# Build *only* dependencies to leverage Docker cache
# This dummy build caches dependencies as a separate layer
RUN --mount=type=ssh mkdir src && \ RUN --mount=type=ssh mkdir src && \
echo "fn main() {println!(\"if you see this, the build broke\")}" > src/main.rs && \ echo "fn main() {println!(\"if you see this, the build broke\")}" > src/main.rs && \
cargo build --release --quiet && \ cargo build --release --quiet && \
rm -rf src target/release/deps/icarus_auth* # Clean up dummy build artifacts (replace icarus_auth) rm -rf src target/release/deps/soaricarus_auth*
# Copy the actual source code
COPY src ./src COPY src ./src
# If you have other directories like `templates` or `static`, copy them too # If you have other directories like `templates` or `static`, copy them too
COPY .env ./.env COPY .env ./.env
COPY migrations ./migrations COPY migrations ./migrations
# << --- SSH MOUNT ADDED HERE --- >>
# Build *only* dependencies to leverage Docker cache
# This dummy build caches dependencies as a separate layer
# Mount the SSH agent socket for this command
RUN --mount=type=ssh \ RUN --mount=type=ssh \
cargo build --release --quiet cargo build --release --quiet
# Stage 2: Create the final, smaller runtime image
# Use a minimal base image like debian-slim or even distroless for security/size
FROM debian:trixie-slim FROM debian:trixie-slim
# Install runtime dependencies if needed (e.g., SSL certificates) # Install runtime dependencies if needed (e.g., SSL certificates)
@@ -55,17 +38,15 @@ RUN apt-get update && apt-get install -y ca-certificates libssl-dev libssl3 && r
WORKDIR /usr/local/bin WORKDIR /usr/local/bin
# Copy the compiled binary from the builder stage # Copy the compiled binary from the builder stage
# Replace 'icarus_auth' with the actual name of your binary (usually the crate name) COPY --from=builder /usr/src/app/target/release/soaricarus_auth .
COPY --from=builder /usr/src/app/target/release/icarus_auth .
# Copy other necessary files like .env (if used for runtime config) or static assets # Copy other necessary files like .env (if used for runtime config) or static assets
# It's generally better to configure via environment variables in Docker though # It's generally better to configure via environment variables in Docker though
COPY --from=builder /usr/src/app/.env . COPY --from=builder /usr/src/app/.env .
COPY --from=builder /usr/src/app/migrations ./migrations COPY --from=builder /usr/src/app/migrations ./migrations
# Expose the port your Axum app listens on (e.g., 3000 or 8000)
EXPOSE 8001 EXPOSE 8001
# Set the command to run your application # Set the command to run your application
# Ensure this matches the binary name copied above # Ensure this matches the binary name copied above
CMD ["./icarus_auth"] CMD ["./soaricarus_auth"]
+22
View File
@@ -0,0 +1,22 @@
Copyright (c) 2026 Kun Deng.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
+2 -1
View File
@@ -1,4 +1,5 @@
A auth web API services for the Icarus project. # soaricarus_auth
A auth web API services for the soaricarus project.
# Getting Started # Getting Started
+12 -17
View File
@@ -1,35 +1,31 @@
version: '3.8' # Use a recent version version: '3.8' # Use a recent version
services: services:
# Your Rust Application Service
auth_api: auth_api:
build: # Tells docker-compose to build the Dockerfile in the current directory build:
context: . context: .
ssh: ["default"] # Uses host's SSH agent ssh: ["default"]
container_name: icarus_auth # Optional: Give the container a specific name container_name: soaricarus_auth
ports: ports:
# Map host port 8000 to container port 3000 (adjust as needed)
- "8001:8001" - "8001:8001"
env_file: env_file:
- .env - .env
depends_on: depends_on:
auth_db: auth_db:
condition: service_healthy # Wait for the DB to be healthy before starting the app condition: service_healthy
restart: unless-stopped # Optional: Restart policy restart: unless-stopped
# PostgreSQL Database Service
auth_db: auth_db:
image: postgres:18.3-alpine # Use an official Postgres image (Alpine variant is smaller) image: postgres:18.4-alpine
container_name: icarus_auth_db # Optional: Give the container a specific name container_name: soaricarus_auth_db
environment: environment:
# These MUST match the user, password, and database name in the DATABASE_URL above POSTGRES_USER: ${POSTGRES_AUTH_USER:-soaricarus_op}
POSTGRES_USER: ${POSTGRES_AUTH_USER:-icarus_op}
POSTGRES_PASSWORD: ${POSTGRES_AUTH_PASSWORD:-password} POSTGRES_PASSWORD: ${POSTGRES_AUTH_PASSWORD:-password}
POSTGRES_DB: ${POSTGRES_AUTH_DB:-icarus_auth_db} POSTGRES_DB: ${POSTGRES_AUTH_DB:-soaricarus_auth_db}
volumes: volumes:
# Persist database data using a named volume
- postgres_data:/var/lib/postgresql - postgres_data:/var/lib/postgresql
ports: [] ports:
- "5433:5432"
healthcheck: healthcheck:
# Checks if Postgres is ready to accept connections # Checks if Postgres is ready to accept connections
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
@@ -37,9 +33,8 @@ services:
timeout: 5s timeout: 5s
retries: 5 retries: 5
start_period: 10s start_period: 10s
restart: always # Optional: Restart policy restart: always
# Define the named volume for data persistence
volumes: volumes:
postgres_data: postgres_data:
driver: local # Use the default local driver driver: local # Use the default local driver
+12 -12
View File
@@ -28,14 +28,14 @@ pub mod response {
#[derive(Default, Deserialize, Serialize, utoipa::ToSchema)] #[derive(Default, Deserialize, Serialize, utoipa::ToSchema)]
pub struct Response { pub struct Response {
pub message: String, pub message: String,
pub data: Vec<icarus_models::login_result::LoginResult>, pub data: Vec<simodels::login_result::LoginResult>,
} }
pub mod service_login { pub mod service_login {
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)] #[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Response { pub struct Response {
pub message: String, pub message: String,
pub data: Vec<icarus_models::login_result::LoginResult>, pub data: Vec<simodels::login_result::LoginResult>,
} }
} }
@@ -43,7 +43,7 @@ pub mod response {
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)] #[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Response { pub struct Response {
pub message: String, pub message: String,
pub data: Vec<icarus_models::login_result::LoginResult>, pub data: Vec<simodels::login_result::LoginResult>,
} }
} }
} }
@@ -92,7 +92,7 @@ pub mod endpoint {
Ok(user) => { Ok(user) => {
if hashing::verify_password(&payload.password, user.password.clone()).unwrap() { if hashing::verify_password(&payload.password, user.password.clone()).unwrap() {
// Create token // Create token
let key = icarus_envy::environment::get_secret_key().await.value; let key = sienvy::environment::get_secret_key().value;
let (token_literal, duration) = let (token_literal, duration) =
token_stuff::create_token(&key, &user.id).unwrap(); token_stuff::create_token(&key, &user.id).unwrap();
@@ -104,11 +104,11 @@ pub mod endpoint {
StatusCode::OK, StatusCode::OK,
Json(response::Response { Json(response::Response {
message: String::from("Successful"), message: String::from("Successful"),
data: vec![icarus_models::login_result::LoginResult { data: vec![simodels::login_result::LoginResult {
id: user.id, id: user.id,
username: user.username.clone(), username: user.username.clone(),
token: token_literal, token: token_literal,
token_type: String::from(icarus_models::token::TOKEN_TYPE), token_type: String::from(simodels::token::TOKEN_TYPE),
expiration: duration, expiration: duration,
}], }],
}), }),
@@ -151,16 +151,16 @@ pub mod endpoint {
match repo::service::valid_passphrase(&pool, &payload.passphrase).await { match repo::service::valid_passphrase(&pool, &payload.passphrase).await {
Ok((id, username, _date_created)) => { Ok((id, username, _date_created)) => {
let key = icarus_envy::environment::get_secret_key().await.value; let key = sienvy::environment::get_secret_key().value;
let (token_literal, duration) = let (token_literal, duration) =
token_stuff::create_service_token(&key, &id).unwrap(); token_stuff::create_service_token(&key, &id).unwrap();
if token_stuff::verify_token(&key, &token_literal) { if token_stuff::verify_token(&key, &token_literal) {
let login_result = icarus_models::login_result::LoginResult { let login_result = simodels::login_result::LoginResult {
id, id,
username, username,
token: token_literal, token: token_literal,
token_type: String::from(icarus_models::token::TOKEN_TYPE), token_type: String::from(simodels::token::TOKEN_TYPE),
expiration: duration, expiration: duration,
}; };
@@ -203,7 +203,7 @@ pub mod endpoint {
axum::Json<response::refresh_token::Response>, axum::Json<response::refresh_token::Response>,
) { ) {
let mut response = response::refresh_token::Response::default(); let mut response = response::refresh_token::Response::default();
let key = icarus_envy::environment::get_secret_key().await.value; let key = sienvy::environment::get_secret_key().value;
if token_stuff::verify_token(&key, &payload.access_token) { if token_stuff::verify_token(&key, &payload.access_token) {
let token_type = token_stuff::get_token_type(&key, &payload.access_token).unwrap(); let token_type = token_stuff::get_token_type(&key, &payload.access_token).unwrap();
@@ -215,11 +215,11 @@ pub mod endpoint {
Ok((username, _, _)) => { Ok((username, _, _)) => {
match token_stuff::create_service_refresh_token(&key, &id) { match token_stuff::create_service_refresh_token(&key, &id) {
Ok((access_token, exp_dur)) => { Ok((access_token, exp_dur)) => {
let login_result = icarus_models::login_result::LoginResult { let login_result = simodels::login_result::LoginResult {
id, id,
token: access_token, token: access_token,
expiration: exp_dur, expiration: exp_dur,
token_type: String::from(icarus_models::token::TOKEN_TYPE), token_type: String::from(simodels::token::TOKEN_TYPE),
username, username,
}; };
response.message = String::from("Successful"); response.message = String::from("Successful");
+4 -4
View File
@@ -29,7 +29,7 @@ pub mod response {
#[derive(Deserialize, Serialize, utoipa::ToSchema)] #[derive(Deserialize, Serialize, utoipa::ToSchema)]
pub struct Response { pub struct Response {
pub message: String, pub message: String,
pub data: Vec<icarus_models::user::User>, pub data: Vec<simodels::user::User>,
} }
} }
@@ -67,7 +67,7 @@ pub async fn register_user(
}; };
if registration_enabled { if registration_enabled {
let mut user = icarus_models::user::User { let mut user = simodels::user::User {
username: payload.username.clone(), username: payload.username.clone(),
password: payload.password.clone(), password: payload.password.clone(),
email: payload.email.clone(), email: payload.email.clone(),
@@ -91,7 +91,7 @@ pub async fn register_user(
) )
} else { } else {
let salt_string = hashing::generate_salt().unwrap(); let salt_string = hashing::generate_salt().unwrap();
let mut salt = icarus_models::user::salt::Salt::default(); let mut salt = simodels::user::salt::Salt::default();
let generated_salt = salt_string; let generated_salt = salt_string;
salt.salt = generated_salt.to_string(); salt.salt = generated_salt.to_string();
salt.id = repo::salt::insert(&pool, &salt).await.unwrap(); salt.id = repo::salt::insert(&pool, &salt).await.unwrap();
@@ -144,7 +144,7 @@ pub async fn register_user(
/// Checks to see if registration is enabled /// Checks to see if registration is enabled
async fn is_registration_enabled() -> Result<bool, std::io::Error> { async fn is_registration_enabled() -> Result<bool, std::io::Error> {
let key = String::from("ENABLE_REGISTRATION"); let key = String::from("ENABLE_REGISTRATION");
let var = icarus_envy::environment::get_env(&key).await; let var = sienvy::environment::get_env(&key);
let parsed_value = var.value.to_uppercase(); let parsed_value = var.value.to_uppercase();
if parsed_value == "TRUE" { if parsed_value == "TRUE" {
+1 -1
View File
@@ -1,7 +1,7 @@
use sqlx::postgres::PgPoolOptions; use sqlx::postgres::PgPoolOptions;
pub async fn create_pool() -> Result<sqlx::PgPool, sqlx::Error> { pub async fn create_pool() -> Result<sqlx::PgPool, sqlx::Error> {
let database_url = icarus_envy::environment::get_db_url().await.value; let database_url = sienvy::environment::get_db_url().value;
println!("Database url: {database_url}"); println!("Database url: {database_url}");
PgPoolOptions::new() PgPoolOptions::new()
+15 -10
View File
@@ -44,7 +44,7 @@ mod init {
register_responses::Response, register_responses::Response,
login_responses::Response, login_responses::service_login::Response, login_responses::refresh_token::Response)), login_responses::Response, login_responses::service_login::Response, login_responses::refresh_token::Response)),
tags( tags(
(name = "Icarus Auth API", description = "Auth API for Icarus API") (name = "soaricarus Auth API", description = "Auth API for soaricarus API")
) )
)] )]
struct ApiDoc; struct ApiDoc;
@@ -67,10 +67,10 @@ mod init {
.max_age(std::time::Duration::from_secs(3600)); // Cache the preflight response for 1 hour:cite[2] .max_age(std::time::Duration::from_secs(3600)); // Cache the preflight response for 1 hour:cite[2]
// Dynamically set the allowed origin based on the environment // Dynamically set the allowed origin based on the environment
match std::env::var(icarus_envy::keys::APP_ENV).as_deref() { match std::env::var(sienvy::keys::APP_ENV).as_deref() {
Ok("production") => { Ok("production") => {
let allowed_origins_env = icarus_envy::environment::get_allowed_origins().await; let allowed_origins_env = sienvy::environment::get_allowed_origins();
match icarus_envy::utility::delimitize(&allowed_origins_env) { match sienvy::utility::delimitize(&allowed_origins_env) {
Ok(alwd) => { Ok(alwd) => {
let allowed_origins: Vec<axum::http::HeaderValue> = alwd let allowed_origins: Vec<axum::http::HeaderValue> = alwd
.into_iter() .into_iter()
@@ -162,7 +162,7 @@ mod tests {
pub const LIMIT: usize = 6; pub const LIMIT: usize = 6;
pub async fn get_pool() -> Result<sqlx::PgPool, sqlx::Error> { pub async fn get_pool() -> Result<sqlx::PgPool, sqlx::Error> {
let tm_db_url = icarus_envy::environment::get_db_url().await.value; let tm_db_url = sienvy::environment::get_db_url().value;
let tm_options = sqlx::postgres::PgConnectOptions::from_str(&tm_db_url).unwrap(); let tm_options = sqlx::postgres::PgConnectOptions::from_str(&tm_db_url).unwrap();
sqlx::PgPool::connect_with(tm_options).await sqlx::PgPool::connect_with(tm_options).await
} }
@@ -175,7 +175,7 @@ mod tests {
} }
pub async fn connect_to_db(db_name: &str) -> Result<sqlx::PgPool, sqlx::Error> { pub async fn connect_to_db(db_name: &str) -> Result<sqlx::PgPool, sqlx::Error> {
let db_url = icarus_envy::environment::get_db_url().await.value; let db_url = sienvy::environment::get_db_url().value;
let options = sqlx::postgres::PgConnectOptions::from_str(&db_url)?.database(db_name); let options = sqlx::postgres::PgConnectOptions::from_str(&db_url)?.database(db_name);
sqlx::PgPool::connect_with(options).await sqlx::PgPool::connect_with(options).await
} }
@@ -185,7 +185,10 @@ mod tests {
db_name: &str, db_name: &str,
) -> Result<(), sqlx::Error> { ) -> Result<(), sqlx::Error> {
let create_query = format!("CREATE DATABASE {}", db_name); let create_query = format!("CREATE DATABASE {}", db_name);
match sqlx::query(&create_query).execute(template_pool).await { match sqlx::query(sqlx::AssertSqlSafe(create_query))
.execute(template_pool)
.await
{
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(e) => Err(e), Err(e) => Err(e),
} }
@@ -197,12 +200,14 @@ mod tests {
db_name: &str, db_name: &str,
) -> Result<(), sqlx::Error> { ) -> Result<(), sqlx::Error> {
let drop_query = format!("DROP DATABASE IF EXISTS {} WITH (FORCE)", db_name); let drop_query = format!("DROP DATABASE IF EXISTS {} WITH (FORCE)", db_name);
sqlx::query(&drop_query).execute(template_pool).await?; sqlx::query(sqlx::AssertSqlSafe(drop_query))
.execute(template_pool)
.await?;
Ok(()) Ok(())
} }
pub async fn get_database_name() -> Result<String, Box<dyn std::error::Error>> { pub async fn get_database_name() -> Result<String, Box<dyn std::error::Error>> {
let database_url = icarus_envy::environment::get_db_url().await.value; let database_url = sienvy::environment::get_db_url().value;
let parsed_url = url::Url::parse(&database_url)?; let parsed_url = url::Url::parse(&database_url)?;
if parsed_url.scheme() == "postgres" || parsed_url.scheme() == "postgresql" { if parsed_url.scheme() == "postgres" || parsed_url.scheme() == "postgresql" {
@@ -503,7 +508,7 @@ mod tests {
let app = init::routes().await.layer(axum::Extension(pool)); let app = init::routes().await.layer(axum::Extension(pool));
let id = uuid::Uuid::parse_str("22f9c775-cce9-457a-a147-9dafbb801f61").unwrap(); let id = uuid::Uuid::parse_str("22f9c775-cce9-457a-a147-9dafbb801f61").unwrap();
let key = icarus_envy::environment::get_secret_key().await.value; let key = sienvy::environment::get_secret_key().value;
match token_stuff::create_service_token(&key, &id) { match token_stuff::create_service_token(&key, &id) {
Ok((token, _expire)) => { Ok((token, _expire)) => {
+7 -7
View File
@@ -12,7 +12,7 @@ pub mod user {
pub async fn get( pub async fn get(
pool: &sqlx::PgPool, pool: &sqlx::PgPool,
username: &String, username: &String,
) -> Result<icarus_models::user::User, sqlx::Error> { ) -> Result<simodels::user::User, sqlx::Error> {
let result = sqlx::query( let result = sqlx::query(
r#" r#"
SELECT * FROM "user" WHERE username = $1 SELECT * FROM "user" WHERE username = $1
@@ -24,7 +24,7 @@ pub mod user {
match result { match result {
Ok(r) => match r { Ok(r) => match r {
Some(r) => Ok(icarus_models::user::User { Some(r) => Ok(simodels::user::User {
id: r.try_get("id")?, id: r.try_get("id")?,
username: r.try_get("username")?, username: r.try_get("username")?,
password: r.try_get("password")?, password: r.try_get("password")?,
@@ -46,7 +46,7 @@ pub mod user {
pub async fn update_last_login( pub async fn update_last_login(
pool: &sqlx::PgPool, pool: &sqlx::PgPool,
user: &icarus_models::user::User, user: &simodels::user::User,
time: &time::OffsetDateTime, time: &time::OffsetDateTime,
) -> Result<time::OffsetDateTime, sqlx::Error> { ) -> Result<time::OffsetDateTime, sqlx::Error> {
let result = sqlx::query( let result = sqlx::query(
@@ -95,7 +95,7 @@ pub mod user {
pub async fn insert( pub async fn insert(
pool: &sqlx::PgPool, pool: &sqlx::PgPool,
user: &icarus_models::user::User, user: &simodels::user::User,
) -> Result<(uuid::Uuid, std::option::Option<time::OffsetDateTime>), sqlx::Error> { ) -> Result<(uuid::Uuid, std::option::Option<time::OffsetDateTime>), sqlx::Error> {
let row = sqlx::query( let row = sqlx::query(
r#" r#"
@@ -145,7 +145,7 @@ pub mod salt {
pub async fn get( pub async fn get(
pool: &sqlx::PgPool, pool: &sqlx::PgPool,
id: &uuid::Uuid, id: &uuid::Uuid,
) -> Result<icarus_models::user::salt::Salt, sqlx::Error> { ) -> Result<simodels::user::salt::Salt, sqlx::Error> {
let result = sqlx::query( let result = sqlx::query(
r#" r#"
SELECT * FROM "salt" WHERE id = $1 SELECT * FROM "salt" WHERE id = $1
@@ -157,7 +157,7 @@ pub mod salt {
match result { match result {
Ok(r) => match r { Ok(r) => match r {
Some(r) => Ok(icarus_models::user::salt::Salt { Some(r) => Ok(simodels::user::salt::Salt {
id: r.try_get("id")?, id: r.try_get("id")?,
salt: r.try_get("salt")?, salt: r.try_get("salt")?,
}), }),
@@ -169,7 +169,7 @@ pub mod salt {
pub async fn insert( pub async fn insert(
pool: &sqlx::PgPool, pool: &sqlx::PgPool,
salt: &icarus_models::user::salt::Salt, salt: &simodels::user::salt::Salt,
) -> Result<uuid::Uuid, sqlx::Error> { ) -> Result<uuid::Uuid, sqlx::Error> {
let row = sqlx::query( let row = sqlx::query(
r#" r#"
+11 -14
View File
@@ -8,8 +8,8 @@ use time;
pub const KEY_ENV: &str = "SECRET_KEY"; pub const KEY_ENV: &str = "SECRET_KEY";
pub const MESSAGE: &str = "Something random"; pub const MESSAGE: &str = "Something random";
pub const ISSUER: &str = "icarus_auth"; pub const ISSUER: &str = "soaricarus_auth";
pub const AUDIENCE: &str = "icarus"; pub const AUDIENCE: &str = "soaricarus";
pub fn get_issued() -> time::Result<time::OffsetDateTime> { pub fn get_issued() -> time::Result<time::OffsetDateTime> {
Ok(time::OffsetDateTime::now_utc()) Ok(time::OffsetDateTime::now_utc())
@@ -24,39 +24,39 @@ pub fn create_token(
provided_key: &String, provided_key: &String,
id: &uuid::Uuid, id: &uuid::Uuid,
) -> Result<(String, i64), josekit::JoseError> { ) -> Result<(String, i64), josekit::JoseError> {
let resource = icarus_models::token::TokenResource { let resource = simodels::token::TokenResource {
message: String::from(MESSAGE), message: String::from(MESSAGE),
issuer: String::from(ISSUER), issuer: String::from(ISSUER),
audiences: vec![String::from(AUDIENCE)], audiences: vec![String::from(AUDIENCE)],
id: *id, id: *id,
}; };
icarus_models::token::create_token(provided_key, &resource, time::Duration::hours(4)) simodels::token::create_token(provided_key, &resource, time::Duration::hours(4))
} }
pub fn create_service_token( pub fn create_service_token(
provided: &String, provided: &String,
id: &uuid::Uuid, id: &uuid::Uuid,
) -> Result<(String, i64), josekit::JoseError> { ) -> Result<(String, i64), josekit::JoseError> {
let resource = icarus_models::token::TokenResource { let resource = simodels::token::TokenResource {
message: String::from(SERVICE_SUBJECT), message: String::from(SERVICE_SUBJECT),
issuer: String::from(ISSUER), issuer: String::from(ISSUER),
audiences: vec![String::from(AUDIENCE)], audiences: vec![String::from(AUDIENCE)],
id: *id, id: *id,
}; };
icarus_models::token::create_token(provided, &resource, time::Duration::hours(1)) simodels::token::create_token(provided, &resource, time::Duration::hours(1))
} }
pub fn create_service_refresh_token( pub fn create_service_refresh_token(
key: &String, key: &String,
id: &uuid::Uuid, id: &uuid::Uuid,
) -> Result<(String, i64), josekit::JoseError> { ) -> Result<(String, i64), josekit::JoseError> {
let resource = icarus_models::token::TokenResource { let resource = simodels::token::TokenResource {
message: String::from(SERVICE_SUBJECT), message: String::from(SERVICE_SUBJECT),
issuer: String::from(ISSUER), issuer: String::from(ISSUER),
audiences: vec![String::from(AUDIENCE)], audiences: vec![String::from(AUDIENCE)],
id: *id, id: *id,
}; };
icarus_models::token::create_token(key, &resource, time::Duration::hours(4)) simodels::token::create_token(key, &resource, time::Duration::hours(4))
} }
pub fn verify_token(key: &String, token: &String) -> bool { pub fn verify_token(key: &String, token: &String) -> bool {
@@ -82,9 +82,9 @@ pub fn extract_id_from_token(key: &String, token: &String) -> Result<uuid::Uuid,
} }
} }
pub const APP_TOKEN_TYPE: &str = "Icarus_App"; pub const APP_TOKEN_TYPE: &str = "SoarIcarus_App";
pub const APP_SUBJECT: &str = "Something random"; pub const APP_SUBJECT: &str = "Something random";
pub const SERVICE_TOKEN_TYPE: &str = "Icarus_Service"; pub const SERVICE_TOKEN_TYPE: &str = "SoarIcarus_Service";
pub const SERVICE_SUBJECT: &str = "Service random"; pub const SERVICE_SUBJECT: &str = "Service random";
pub fn get_token_type(key: &String, token: &String) -> Result<String, std::io::Error> { pub fn get_token_type(key: &String, token: &String) -> Result<String, std::io::Error> {
@@ -123,10 +123,7 @@ mod tests {
#[test] #[test]
fn test_tokenize() { fn test_tokenize() {
let rt = tokio::runtime::Runtime::new().unwrap(); let special_key = sienvy::environment::get_secret_key().value;
let special_key = rt
.block_on(icarus_envy::environment::get_secret_key())
.value;
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
match create_token(&special_key, &id) { match create_token(&special_key, &id) {
Ok((token, _duration)) => { Ok((token, _duration)) => {