Compare commits

...
4 Commits
Author SHA1 Message Date
phoenix 50ff10ae91 bump: postgres ci
icarus_auth Build / Check (pull_request) Successful in 2m37s
icarus_auth Build / build (pull_request) Successful in 2m6s
icarus_auth Build / Rustfmt (pull_request) Successful in 53s
icarus_auth Build / Test Suite (pull_request) Successful in 1m11s
icarus_auth Build / Clippy (pull_request) Successful in 2m27s
2026-07-09 10:31:22 -04:00
phoenix f4976567ab bump: postgres 2026-07-09 10:31:12 -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
phoenix 54b0710298 Update rust (#1)
Rust Build / Check (push) Successful in 31s
Rust Build / Test Suite (push) Successful in 35s
Rust Build / Clippy (push) Successful in 30s
Rust Build / Rustfmt (push) Successful in 58s
Rust Build / build (push) Successful in 48s
Release Tagging / release (push) Successful in 1m34s
Rust Build / Rustfmt (pull_request) Successful in 34s
Rust Build / Test Suite (pull_request) Successful in 1m37s
Rust Build / Check (pull_request) Successful in 2m6s
Rust Build / Clippy (pull_request) Successful in 1m31s
Rust Build / build (pull_request) Successful in 1m21s
Reviewed-on: phoenix/icarus_auth#1
2026-05-22 11:24:55 -04:00
11 changed files with 352 additions and 811 deletions
+3 -2
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 # Important for git describe --tags
- name: Install Rust - name: Install Rust
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
toolchain: 1.94 toolchain: 1.96.1
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
+17 -21
View File
@@ -1,24 +1,23 @@
name: Rust Build name: icarus_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.94 toolchain: 1.96.1
- 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/icarus_models_deploy_key
@@ -33,16 +32,13 @@ jobs:
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.94 toolchain: 1.96.1
# --- 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,15 +62,12 @@ 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: |
@@ -92,10 +85,11 @@ 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.94 toolchain: 1.96.1
- uses: Swatinem/rust-cache@v2
- run: rustup component add rustfmt - run: rustup component add rustfmt
- run: | - run: |
mkdir -p ~/.ssh mkdir -p ~/.ssh
@@ -111,10 +105,11 @@ jobs:
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.94 toolchain: 1.96.1
- uses: Swatinem/rust-cache@v2
- run: rustup component add clippy - run: rustup component add clippy
- run: | - run: |
mkdir -p ~/.ssh mkdir -p ~/.ssh
@@ -130,10 +125,11 @@ jobs:
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.94 toolchain: 1.96.1
- 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/icarus_models_deploy_key
Generated
+289 -739
View File
File diff suppressed because it is too large Load Diff
+14 -16
View File
@@ -1,30 +1,28 @@
[package] [package]
name = "icarus_auth" name = "icarus_auth"
version = "0.7.0" version = "0.8.1"
edition = "2024" edition = "2024"
rust-version = "1.94" rust-version = "1.95"
[dependencies] [dependencies]
axum = { version = "0.8.8" } 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.51", 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.8", 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.4", features = ["v4", "serde"] }
uuid = { version = "1.23", 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.0" }
time = { version = "0.3.47", features = ["macros", "serde"] }
josekit = { version = "0.10.3" } josekit = { version = "0.10.3" }
utoipa = { version = "5.4.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.10.0" } icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.11.3" }
icarus_envy = { git = "ssh://git@git.kundeng.us/phoenix/icarus_envy.git", tag = "v0.6.0" } icarus_envy = { git = "ssh://git@git.kundeng.us/phoenix/icarus_envy.git", tag = "v0.8.0" }
[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
+2 -2
View File
@@ -1,7 +1,7 @@
# Stage 1: Build the application # Stage 1: Build the application
# Use a specific Rust version for reproducibility. Choose one that matches your development environment. # Use a specific Rust version for reproducibility. Choose one that matches your development environment.
# Using slim variant for smaller base image # Using slim variant for smaller base image
FROM rust:1.94 as builder FROM rust:1.96.1 as builder
# Set the working directory inside the container # Set the working directory inside the container
WORKDIR /usr/src/app WORKDIR /usr/src/app
@@ -46,7 +46,7 @@ RUN --mount=type=ssh \
# Stage 2: Create the final, smaller runtime image # Stage 2: Create the final, smaller runtime image
# Use a minimal base image like debian-slim or even distroless for security/size # Use a minimal base image like debian-slim or even distroless for security/size
FROM ubuntu:24.04 FROM debian:trixie-slim
# Install runtime dependencies if needed (e.g., SSL certificates) # Install runtime dependencies if needed (e.g., SSL certificates)
RUN apt-get update && apt-get install -y ca-certificates libssl-dev libssl3 && rm -rf /var/lib/apt/lists/* RUN apt-get update && apt-get install -y ca-certificates libssl-dev libssl3 && rm -rf /var/lib/apt/lists/*
+9 -15
View File
@@ -1,34 +1,29 @@
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: icarus_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: icarus_auth_db
environment: environment:
# These MUST match the user, password, and database name in the DATABASE_URL above
POSTGRES_USER: ${POSTGRES_AUTH_USER:-icarus_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:-icarus_auth_db}
volumes: volumes:
# Persist database data using a named volume - postgres_data:/var/lib/postgresql
- postgres_data:/var/lib/postgresql/data
ports: [] ports: []
healthcheck: healthcheck:
# Checks if Postgres is ready to accept connections # Checks if Postgres is ready to accept connections
@@ -37,9 +32,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
+3 -3
View File
@@ -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 = icarus_envy::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();
@@ -151,7 +151,7 @@ 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 = icarus_envy::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();
@@ -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 = icarus_envy::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();
+1 -1
View File
@@ -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 = icarus_envy::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 = icarus_envy::environment::get_db_url().value;
println!("Database url: {database_url}"); println!("Database url: {database_url}");
PgPoolOptions::new() PgPoolOptions::new()
+12 -7
View File
@@ -69,7 +69,7 @@ mod init {
// 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(icarus_envy::keys::APP_ENV).as_deref() {
Ok("production") => { Ok("production") => {
let allowed_origins_env = icarus_envy::environment::get_allowed_origins().await; let allowed_origins_env = icarus_envy::environment::get_allowed_origins();
match icarus_envy::utility::delimitize(&allowed_origins_env) { match icarus_envy::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
@@ -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 = icarus_envy::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 = icarus_envy::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 = icarus_envy::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 = icarus_envy::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)) => {
+1 -4
View File
@@ -123,10 +123,7 @@ mod tests {
#[test] #[test]
fn test_tokenize() { fn test_tokenize() {
let rt = tokio::runtime::Runtime::new().unwrap(); let special_key = icarus_envy::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)) => {