diff --git a/frontend/src/components/Auth/__tests__/Login.oidc.test.tsx b/frontend/src/components/Auth/__tests__/Login.oidc.test.tsx
index f51eb15..9232e0b 100644
--- a/frontend/src/components/Auth/__tests__/Login.oidc.test.tsx
+++ b/frontend/src/components/Auth/__tests__/Login.oidc.test.tsx
@@ -44,6 +44,7 @@ Object.defineProperty(window, 'location', {
writable: true
});
+
// Mock AuthContext
const mockAuthContextValue = {
user: null,
@@ -54,16 +55,35 @@ const mockAuthContextValue = {
};
const MockAuthProvider = ({ children }: { children: React.ReactNode }) => (
-
{children}
+
+ {children}
+
);
const MockThemeProvider = ({ children }: { children: React.ReactNode }) => (
- {children}
+
+ {children}
+
);
describe('Login - OIDC Features', () => {
beforeEach(() => {
vi.clearAllMocks();
+
+ // Mock window.matchMedia
+ Object.defineProperty(window, 'matchMedia', {
+ writable: true,
+ value: vi.fn().mockImplementation(query => ({
+ matches: false,
+ media: query,
+ onchange: null,
+ addListener: vi.fn(),
+ removeListener: vi.fn(),
+ addEventListener: vi.fn(),
+ removeEventListener: vi.fn(),
+ dispatchEvent: vi.fn(),
+ })),
+ });
});
const renderLogin = () => {
diff --git a/frontend/src/components/Auth/__tests__/OidcCallback.test.tsx b/frontend/src/components/Auth/__tests__/OidcCallback.test.tsx
index c4a5f6b..37c2601 100644
--- a/frontend/src/components/Auth/__tests__/OidcCallback.test.tsx
+++ b/frontend/src/components/Auth/__tests__/OidcCallback.test.tsx
@@ -17,14 +17,16 @@ vi.mock('../../../services/api', () => ({
}
}));
-// Mock useNavigate
+// Mock useNavigate and useSearchParams
const mockNavigate = vi.fn();
+const mockUseSearchParams = vi.fn(() => [new URLSearchParams('code=test-code&state=test-state')]);
+
vi.mock('react-router-dom', async () => {
const actual = await vi.importActual('react-router-dom');
return {
...actual,
useNavigate: () => mockNavigate,
- useSearchParams: () => [new URLSearchParams('code=test-code&state=test-state')]
+ useSearchParams: mockUseSearchParams
};
});
@@ -45,6 +47,7 @@ Object.defineProperty(window, 'location', {
writable: true
});
+
// Mock AuthContext
const mockAuthContextValue = {
user: null,
@@ -55,12 +58,29 @@ const mockAuthContextValue = {
};
const MockAuthProvider = ({ children }: { children: React.ReactNode }) => (
- {children}
+
+ {children}
+
);
describe('OidcCallback', () => {
beforeEach(() => {
vi.clearAllMocks();
+
+ // Mock window.matchMedia
+ Object.defineProperty(window, 'matchMedia', {
+ writable: true,
+ value: vi.fn().mockImplementation(query => ({
+ matches: false,
+ media: query,
+ onchange: null,
+ addListener: vi.fn(),
+ removeListener: vi.fn(),
+ addEventListener: vi.fn(),
+ removeEventListener: vi.fn(),
+ dispatchEvent: vi.fn(),
+ })),
+ });
});
const renderOidcCallback = () => {
@@ -106,7 +126,7 @@ describe('OidcCallback', () => {
it('handles authentication error from URL params', () => {
// Mock useSearchParams to return error
- vi.mocked(require('react-router-dom').useSearchParams).mockReturnValue([
+ mockUseSearchParams.mockReturnValueOnce([
new URLSearchParams('error=access_denied&error_description=User+denied+access')
]);
@@ -118,7 +138,7 @@ describe('OidcCallback', () => {
it('handles missing authorization code', () => {
// Mock useSearchParams to return no code
- vi.mocked(require('react-router-dom').useSearchParams).mockReturnValue([
+ mockUseSearchParams.mockReturnValueOnce([
new URLSearchParams('')
]);
diff --git a/frontend/src/test/setup.ts b/frontend/src/test/setup.ts
index ea93d68..2286153 100644
--- a/frontend/src/test/setup.ts
+++ b/frontend/src/test/setup.ts
@@ -19,4 +19,19 @@ vi.mock('axios', () => ({
defaults: { headers: { common: {} } },
})),
},
-}))
\ No newline at end of file
+}))
+
+// Mock window.matchMedia
+Object.defineProperty(window, 'matchMedia', {
+ writable: true,
+ value: vi.fn().mockImplementation(query => ({
+ matches: false,
+ media: query,
+ onchange: null,
+ addListener: vi.fn(), // deprecated
+ removeListener: vi.fn(), // deprecated
+ addEventListener: vi.fn(),
+ removeEventListener: vi.fn(),
+ dispatchEvent: vi.fn(),
+ })),
+})
\ No newline at end of file
diff --git a/src/db/mod.rs b/src/db/mod.rs
index 288f28c..e1d28bf 100644
--- a/src/db/mod.rs
+++ b/src/db/mod.rs
@@ -88,23 +88,41 @@ impl Database {
.execute(&self.pool)
.await?;
- // Create users table
+ // Create users table with OIDC support
sqlx::query(
r#"
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
username VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
- password_hash VARCHAR(255) NOT NULL,
- role VARCHAR(10) DEFAULT 'user',
+ password_hash VARCHAR(255),
+ role VARCHAR(20) DEFAULT 'user',
created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW()
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ oidc_subject VARCHAR(255),
+ oidc_issuer VARCHAR(255),
+ oidc_email VARCHAR(255),
+ auth_provider VARCHAR(50) DEFAULT 'local',
+ CONSTRAINT check_auth_method CHECK (
+ (auth_provider = 'local' AND password_hash IS NOT NULL) OR
+ (auth_provider = 'oidc' AND oidc_subject IS NOT NULL AND oidc_issuer IS NOT NULL)
+ ),
+ CONSTRAINT check_user_role CHECK (role IN ('admin', 'user'))
)
"#,
)
.execute(&self.pool)
.await?;
+ // Create indexes for OIDC
+ sqlx::query(r#"CREATE INDEX IF NOT EXISTS idx_users_oidc_subject_issuer ON users(oidc_subject, oidc_issuer)"#)
+ .execute(&self.pool)
+ .await?;
+
+ sqlx::query(r#"CREATE INDEX IF NOT EXISTS idx_users_auth_provider ON users(auth_provider)"#)
+ .execute(&self.pool)
+ .await?;
+
// Create documents table
sqlx::query(
diff --git a/src/routes/auth.rs b/src/routes/auth.rs
index 7c20f8f..5091c3f 100644
--- a/src/routes/auth.rs
+++ b/src/routes/auth.rs
@@ -23,6 +23,7 @@ pub fn router() -> Router> {
.route("/oidc/callback", get(oidc_callback))
}
+
#[utoipa::path(
post,
path = "/api/auth/register",
@@ -170,6 +171,9 @@ async fn oidc_callback(
State(state): State>,
Query(params): Query,
) -> Result, StatusCode> {
+ tracing::info!("OIDC callback called with params: code={:?}, state={:?}, error={:?}",
+ params.code, params.state, params.error);
+
if let Some(error) = params.error {
tracing::error!("OIDC callback error: {}", error);
return Err(StatusCode::UNAUTHORIZED);
@@ -201,9 +205,15 @@ async fn oidc_callback(
})?;
// Find or create user in database
- let user = match state.db.get_user_by_oidc_subject(&user_info.sub, &state.config.oidc_issuer_url.as_ref().unwrap()).await {
- Ok(Some(existing_user)) => existing_user,
+ let issuer_url = state.config.oidc_issuer_url.as_ref().unwrap();
+ tracing::debug!("Looking up user by OIDC subject: {} and issuer: {}", user_info.sub, issuer_url);
+ let user = match state.db.get_user_by_oidc_subject(&user_info.sub, issuer_url).await {
+ Ok(Some(existing_user)) => {
+ tracing::debug!("Found existing OIDC user: {}", existing_user.username);
+ existing_user
+ },
Ok(None) => {
+ tracing::debug!("Creating new OIDC user");
// Create new user
let username = user_info.preferred_username
.or_else(|| user_info.email.clone())
@@ -211,6 +221,8 @@ async fn oidc_callback(
let email = user_info.email.unwrap_or_else(|| format!("{}@oidc.local", username));
+ tracing::debug!("New user details - username: {}, email: {}", username, email);
+
let create_user = CreateUser {
username,
email: email.clone(),
@@ -218,15 +230,23 @@ async fn oidc_callback(
role: Some(UserRole::User),
};
- state.db.create_oidc_user(
+ let result = state.db.create_oidc_user(
create_user,
&user_info.sub,
- &state.config.oidc_issuer_url.as_ref().unwrap(),
+ issuer_url,
&email,
- ).await.map_err(|e| {
- tracing::error!("Failed to create OIDC user: {}", e);
- StatusCode::INTERNAL_SERVER_ERROR
- })?
+ ).await;
+
+ match result {
+ Ok(user) => {
+ tracing::info!("Successfully created OIDC user: {}", user.username);
+ user
+ },
+ Err(e) => {
+ tracing::error!("Failed to create OIDC user: {} (full error: {:#})", e, e);
+ return Err(StatusCode::INTERNAL_SERVER_ERROR);
+ }
+ }
}
Err(e) => {
tracing::error!("Database error during OIDC lookup: {}", e);
@@ -236,7 +256,10 @@ async fn oidc_callback(
// Create JWT token
let token = create_jwt(&user, &state.config.jwt_secret)
- .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
+ .map_err(|e| {
+ tracing::error!("Failed to create JWT token: {}", e);
+ StatusCode::INTERNAL_SERVER_ERROR
+ })?;
Ok(Json(LoginResponse {
token,
diff --git a/src/tests/config_oidc_tests.rs b/src/tests/config_oidc_tests.rs
index 321b03c..d6eaff2 100644
--- a/src/tests/config_oidc_tests.rs
+++ b/src/tests/config_oidc_tests.rs
@@ -40,11 +40,22 @@ mod tests {
#[test]
fn test_oidc_enabled_from_env() {
+ // Clean up environment first to ensure test isolation
+ env::remove_var("OIDC_ENABLED");
+ env::remove_var("OIDC_CLIENT_ID");
+ env::remove_var("OIDC_CLIENT_SECRET");
+ env::remove_var("OIDC_ISSUER_URL");
+ env::remove_var("OIDC_REDIRECT_URI");
+ env::remove_var("DATABASE_URL");
+ env::remove_var("JWT_SECRET");
+
env::set_var("OIDC_ENABLED", "true");
env::set_var("OIDC_CLIENT_ID", "test-client-id");
env::set_var("OIDC_CLIENT_SECRET", "test-client-secret");
env::set_var("OIDC_ISSUER_URL", "https://provider.example.com");
env::set_var("OIDC_REDIRECT_URI", "http://localhost:8000/auth/oidc/callback");
+ env::set_var("DATABASE_URL", "postgresql://test:test@localhost/test");
+ env::set_var("JWT_SECRET", "test-secret");
let config = Config::from_env().unwrap();
@@ -60,6 +71,8 @@ mod tests {
env::remove_var("OIDC_CLIENT_SECRET");
env::remove_var("OIDC_ISSUER_URL");
env::remove_var("OIDC_REDIRECT_URI");
+ env::remove_var("DATABASE_URL");
+ env::remove_var("JWT_SECRET");
}
#[test]
@@ -83,6 +96,15 @@ mod tests {
];
for (value, expected) in test_cases {
+ // Clean up environment first for each iteration
+ env::remove_var("OIDC_ENABLED");
+ env::remove_var("OIDC_CLIENT_ID");
+ env::remove_var("OIDC_CLIENT_SECRET");
+ env::remove_var("OIDC_ISSUER_URL");
+ env::remove_var("OIDC_REDIRECT_URI");
+ env::remove_var("DATABASE_URL");
+ env::remove_var("JWT_SECRET");
+
env::set_var("OIDC_ENABLED", value);
env::set_var("DATABASE_URL", "postgresql://test:test@localhost/test");
env::set_var("JWT_SECRET", "test-secret");
diff --git a/src/tests/oidc_tests.rs b/src/tests/oidc_tests.rs
index a20f29f..e088bfd 100644
--- a/src/tests/oidc_tests.rs
+++ b/src/tests/oidc_tests.rs
@@ -1,16 +1,76 @@
#[cfg(test)]
mod tests {
use crate::models::{AuthProvider, CreateUser, UserRole};
- use super::super::helpers::{create_test_app};
use axum::http::StatusCode;
use serde_json::json;
use tower::util::ServiceExt;
- use wiremock::{matchers::{method, path, query_param}, Mock, MockServer, ResponseTemplate};
+ use wiremock::{matchers::{method, path, query_param, header}, Mock, MockServer, ResponseTemplate};
use std::sync::Arc;
use crate::{AppState, oidc::OidcClient};
- async fn create_test_app_with_oidc() -> (axum::Router, testcontainers::ContainerAsync, MockServer) {
- let (mut app, container) = create_test_app().await;
+ async fn create_test_app_simple() -> (axum::Router, ()) {
+ // Use TEST_DATABASE_URL directly, no containers
+ let database_url = std::env::var("TEST_DATABASE_URL")
+ .or_else(|_| std::env::var("DATABASE_URL"))
+ .unwrap_or_else(|_| "postgresql://readur:readur@localhost:5432/readur".to_string());
+
+ let config = crate::config::Config {
+ database_url: database_url.clone(),
+ server_address: "127.0.0.1:0".to_string(),
+ jwt_secret: "test-secret".to_string(),
+ upload_path: "./test-uploads".to_string(),
+ watch_folder: "./test-watch".to_string(),
+ allowed_file_types: vec!["pdf".to_string()],
+ watch_interval_seconds: Some(30),
+ file_stability_check_ms: Some(500),
+ max_file_age_hours: None,
+ ocr_language: "eng".to_string(),
+ concurrent_ocr_jobs: 2,
+ ocr_timeout_seconds: 60,
+ max_file_size_mb: 10,
+ memory_limit_mb: 256,
+ cpu_priority: "normal".to_string(),
+ oidc_enabled: false,
+ oidc_client_id: None,
+ oidc_client_secret: None,
+ oidc_issuer_url: None,
+ oidc_redirect_uri: None,
+ };
+
+ let db = crate::db::Database::new(&config.database_url).await.unwrap();
+
+ // Retry migration up to 3 times to handle concurrent test execution
+ for attempt in 1..=3 {
+ match db.migrate().await {
+ Ok(_) => break,
+ Err(e) if attempt < 3 && e.to_string().contains("tuple concurrently updated") => {
+ // Wait a bit and retry
+ tokio::time::sleep(tokio::time::Duration::from_millis(100 * attempt)).await;
+ continue;
+ }
+ Err(e) => panic!("Migration failed after {} attempts: {}", attempt, e),
+ }
+ }
+
+ let app = axum::Router::new()
+ .nest("/api/auth", crate::routes::auth::router())
+ .with_state(Arc::new(AppState {
+ db: db.clone(),
+ config,
+ webdav_scheduler: None,
+ source_scheduler: None,
+ queue_service: Arc::new(crate::ocr_queue::OcrQueueService::new(
+ db.clone(),
+ db.pool.clone(),
+ 2
+ )),
+ oidc_client: None,
+ }));
+
+ (app, ())
+ }
+
+ async fn create_test_app_with_oidc() -> (axum::Router, MockServer) {
let mock_server = MockServer::start().await;
// Mock OIDC discovery endpoint
@@ -27,9 +87,14 @@ mod tests {
.mount(&mock_server)
.await;
+ // Use TEST_DATABASE_URL directly, no containers
+ let database_url = std::env::var("TEST_DATABASE_URL")
+ .or_else(|_| std::env::var("DATABASE_URL"))
+ .unwrap_or_else(|_| "postgresql://readur:readur@localhost:5432/readur".to_string());
+
// Update the app state to include OIDC client
let config = crate::config::Config {
- database_url: "postgresql://test:test@localhost/test".to_string(),
+ database_url: database_url.clone(),
server_address: "127.0.0.1:0".to_string(),
jwt_secret: "test-secret".to_string(),
upload_path: "./test-uploads".to_string(),
@@ -51,34 +116,51 @@ mod tests {
oidc_redirect_uri: Some("http://localhost:8000/auth/oidc/callback".to_string()),
};
- let oidc_client = OidcClient::new(&config).await.ok().map(Arc::new);
+ let oidc_client = match OidcClient::new(&config).await {
+ Ok(client) => Some(Arc::new(client)),
+ Err(e) => {
+ panic!("OIDC client creation failed: {}", e);
+ }
+ };
- // We need to extract the state from the existing app and recreate it
- // This is a bit hacky, but necessary for testing
- app = axum::Router::new()
+ // Connect to the database and run migrations with retry logic for concurrency
+ let db = crate::db::Database::new(&config.database_url).await.unwrap();
+
+ // Retry migration up to 3 times to handle concurrent test execution
+ for attempt in 1..=3 {
+ match db.migrate().await {
+ Ok(_) => break,
+ Err(e) if attempt < 3 && e.to_string().contains("tuple concurrently updated") => {
+ // Wait a bit and retry
+ tokio::time::sleep(tokio::time::Duration::from_millis(100 * attempt)).await;
+ continue;
+ }
+ Err(e) => panic!("Migration failed after {} attempts: {}", attempt, e),
+ }
+ }
+
+ // Create app with OIDC configuration
+ let app = axum::Router::new()
.nest("/api/auth", crate::routes::auth::router())
.with_state(Arc::new(AppState {
- db: crate::db::Database::new(&format!("postgresql://test:test@localhost:{}/test",
- container.get_host_port_ipv4(5432).await.unwrap())).await.unwrap(),
+ db: db.clone(),
config,
webdav_scheduler: None,
source_scheduler: None,
queue_service: Arc::new(crate::ocr_queue::OcrQueueService::new(
- crate::db::Database::new(&format!("postgresql://test:test@localhost:{}/test",
- container.get_host_port_ipv4(5432).await.unwrap())).await.unwrap(),
- sqlx::PgPool::connect(&format!("postgresql://test:test@localhost:{}/test",
- container.get_host_port_ipv4(5432).await.unwrap())).await.unwrap(),
+ db.clone(),
+ db.pool.clone(),
2
)),
oidc_client,
}));
- (app, container, mock_server)
+ (app, mock_server)
}
#[tokio::test]
async fn test_oidc_login_redirect() {
- let (app, _container, _mock_server) = create_test_app_with_oidc().await;
+ let (app, _mock_server) = create_test_app_with_oidc().await;
let response = app
.oneshot(
@@ -101,7 +183,7 @@ mod tests {
#[tokio::test]
async fn test_oidc_login_disabled() {
- let (app, _container) = create_test_app().await; // Regular app without OIDC
+ let (app, _container) = create_test_app_simple().await; // Regular app without OIDC
let response = app
.oneshot(
@@ -119,7 +201,7 @@ mod tests {
#[tokio::test]
async fn test_oidc_callback_missing_code() {
- let (app, _container, _mock_server) = create_test_app_with_oidc().await;
+ let (app, _mock_server) = create_test_app_with_oidc().await;
let response = app
.oneshot(
@@ -137,7 +219,7 @@ mod tests {
#[tokio::test]
async fn test_oidc_callback_with_error() {
- let (app, _container, _mock_server) = create_test_app_with_oidc().await;
+ let (app, _mock_server) = create_test_app_with_oidc().await;
let response = app
.oneshot(
@@ -155,7 +237,21 @@ mod tests {
#[tokio::test]
async fn test_oidc_callback_success_new_user() {
- let (app, _container, mock_server) = create_test_app_with_oidc().await;
+ let (app, mock_server) = create_test_app_with_oidc().await;
+
+ // Clean up any existing test user to ensure test isolation
+ let database_url = std::env::var("TEST_DATABASE_URL")
+ .or_else(|_| std::env::var("DATABASE_URL"))
+ .unwrap_or_else(|_| "postgresql://readur:readur@localhost:5432/readur".to_string());
+ let db = crate::db::Database::new(&database_url).await.unwrap();
+
+ // Delete any existing user with the test username or OIDC subject
+ let _ = sqlx::query("DELETE FROM users WHERE username = $1 OR oidc_subject = $2")
+ .bind("oidcuser")
+ .bind("oidc-user-123")
+ .execute(&db.pool)
+ .await;
+
// Mock token exchange
let token_response = json!({
@@ -166,7 +262,10 @@ mod tests {
Mock::given(method("POST"))
.and(path("/token"))
- .respond_with(ResponseTemplate::new(200).set_body_json(token_response))
+ .and(header("content-type", "application/x-www-form-urlencoded"))
+ .respond_with(ResponseTemplate::new(200)
+ .set_body_json(token_response)
+ .insert_header("content-type", "application/json"))
.mount(&mock_server)
.await;
@@ -180,10 +279,15 @@ mod tests {
Mock::given(method("GET"))
.and(path("/userinfo"))
- .respond_with(ResponseTemplate::new(200).set_body_json(user_info_response))
+ .respond_with(ResponseTemplate::new(200)
+ .set_body_json(user_info_response)
+ .insert_header("content-type", "application/json"))
.mount(&mock_server)
.await;
+ // Add a small delay to make sure everything is set up
+ tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
+
let response = app
.oneshot(
axum::http::Request::builder()
@@ -195,11 +299,31 @@ mod tests {
.await
.unwrap();
- assert_eq!(response.status(), StatusCode::OK);
-
+ let status = response.status();
let body = axum::body::to_bytes(response.into_body(), usize::MAX)
.await
.unwrap();
+
+ if status != StatusCode::OK {
+ let error_text = String::from_utf8_lossy(&body);
+ eprintln!("Response status: {}", status);
+ eprintln!("Response body: {}", error_text);
+
+ // Also check if we made the expected API calls to the mock server
+ eprintln!("Mock server received calls:");
+ let received_requests = mock_server.received_requests().await.unwrap();
+ for req in received_requests {
+ eprintln!(" {} {} - {}", req.method, req.url.path(), String::from_utf8_lossy(&req.body));
+ }
+
+ // Try to parse as JSON to see if there's a more detailed error message
+ if let Ok(error_json) = serde_json::from_slice::(&body) {
+ eprintln!("Error JSON: {:#}", error_json);
+ }
+ }
+
+ assert_eq!(status, StatusCode::OK);
+
let login_response: serde_json::Value = serde_json::from_slice(&body).unwrap();
assert!(login_response["token"].is_string());
@@ -209,7 +333,7 @@ mod tests {
#[tokio::test]
async fn test_oidc_callback_invalid_token() {
- let (app, _container, mock_server) = create_test_app_with_oidc().await;
+ let (app, mock_server) = create_test_app_with_oidc().await;
// Mock failed token exchange
Mock::given(method("POST"))
@@ -236,7 +360,18 @@ mod tests {
#[tokio::test]
async fn test_oidc_callback_invalid_user_info() {
- let (app, _container, mock_server) = create_test_app_with_oidc().await;
+ let (app, mock_server) = create_test_app_with_oidc().await;
+
+ // Clean up any existing test user to ensure test isolation
+ let database_url = std::env::var("TEST_DATABASE_URL")
+ .or_else(|_| std::env::var("DATABASE_URL"))
+ .unwrap_or_else(|_| "postgresql://readur:readur@localhost:5432/readur".to_string());
+ let db = crate::db::Database::new(&database_url).await.unwrap();
+
+ // Delete any existing user that might conflict
+ let _ = sqlx::query("DELETE FROM users WHERE username LIKE 'oidc%' OR oidc_subject IS NOT NULL")
+ .execute(&db.pool)
+ .await;
// Mock successful token exchange
let token_response = json!({
diff --git a/tests/auto_resume_tests.rs b/tests/auto_resume_tests.rs
index 21fe269..98feeb9 100644
--- a/tests/auto_resume_tests.rs
+++ b/tests/auto_resume_tests.rs
@@ -47,6 +47,11 @@ async fn create_test_app_state() -> Arc {
max_file_size_mb: 50,
memory_limit_mb: 512,
cpu_priority: "normal".to_string(),
+ oidc_enabled: false,
+ oidc_client_id: None,
+ oidc_client_secret: None,
+ oidc_issuer_url: None,
+ oidc_redirect_uri: None,
};
let db = Database::new(&config.database_url).await.unwrap();
@@ -62,6 +67,7 @@ async fn create_test_app_state() -> Arc {
webdav_scheduler: None,
source_scheduler: None,
queue_service,
+ oidc_client: None,
})
}
diff --git a/tests/document_upload_hash_duplicate_tests.rs b/tests/document_upload_hash_duplicate_tests.rs
index 6730dce..ecca3b8 100644
--- a/tests/document_upload_hash_duplicate_tests.rs
+++ b/tests/document_upload_hash_duplicate_tests.rs
@@ -76,6 +76,11 @@ async fn create_test_app_state() -> Result> {
max_file_size_mb: 10,
memory_limit_mb: 256,
cpu_priority: "normal".to_string(),
+ oidc_enabled: false,
+ oidc_client_id: None,
+ oidc_client_secret: None,
+ oidc_issuer_url: None,
+ oidc_redirect_uri: None,
}
});
let db = Database::new(&config.database_url).await?;
@@ -89,6 +94,7 @@ async fn create_test_app_state() -> Result> {
webdav_scheduler: None,
source_scheduler: None,
queue_service,
+ oidc_client: None,
}))
}
diff --git a/tests/ignored_files_integration_tests.rs b/tests/ignored_files_integration_tests.rs
index a349316..48d0b27 100644
--- a/tests/ignored_files_integration_tests.rs
+++ b/tests/ignored_files_integration_tests.rs
@@ -31,6 +31,11 @@ async fn create_test_app_state() -> Result> {
max_file_size_mb: 10,
memory_limit_mb: 256,
cpu_priority: "normal".to_string(),
+ oidc_enabled: false,
+ oidc_client_id: None,
+ oidc_client_secret: None,
+ oidc_issuer_url: None,
+ oidc_redirect_uri: None,
}
});
@@ -43,6 +48,7 @@ async fn create_test_app_state() -> Result> {
webdav_scheduler: None,
source_scheduler: None,
queue_service,
+ oidc_client: None,
}))
}
diff --git a/tests/source_scheduler_simple_tests.rs b/tests/source_scheduler_simple_tests.rs
index 565bf6f..d8c8e1f 100644
--- a/tests/source_scheduler_simple_tests.rs
+++ b/tests/source_scheduler_simple_tests.rs
@@ -39,6 +39,11 @@ async fn create_test_app_state() -> Arc {
max_file_size_mb: 100,
memory_limit_mb: 512,
cpu_priority: "normal".to_string(),
+ oidc_enabled: false,
+ oidc_client_id: None,
+ oidc_client_secret: None,
+ oidc_issuer_url: None,
+ oidc_redirect_uri: None,
};
let db = Database::new(&config.database_url).await.unwrap();
@@ -50,6 +55,7 @@ async fn create_test_app_state() -> Arc {
webdav_scheduler: None,
source_scheduler: None,
queue_service,
+ oidc_client: None,
})
}
diff --git a/tests/source_scheduler_tests.rs b/tests/source_scheduler_tests.rs
index ca24315..91769d4 100644
--- a/tests/source_scheduler_tests.rs
+++ b/tests/source_scheduler_tests.rs
@@ -176,6 +176,11 @@ async fn create_test_app_state() -> Arc {
max_file_size_mb: 10,
memory_limit_mb: 256,
cpu_priority: "normal".to_string(),
+ oidc_enabled: false,
+ oidc_client_id: None,
+ oidc_client_secret: None,
+ oidc_issuer_url: None,
+ oidc_redirect_uri: None,
};
let db = Database::new(&config.database_url).await.unwrap();
@@ -187,6 +192,7 @@ async fn create_test_app_state() -> Arc {
webdav_scheduler: None,
source_scheduler: None,
queue_service,
+ oidc_client: None,
})
}
diff --git a/tests/source_sync_hash_duplicate_tests.rs b/tests/source_sync_hash_duplicate_tests.rs
index baaa25d..642453d 100644
--- a/tests/source_sync_hash_duplicate_tests.rs
+++ b/tests/source_sync_hash_duplicate_tests.rs
@@ -113,6 +113,11 @@ async fn create_test_app_state() -> Result> {
max_file_size_mb: 10,
memory_limit_mb: 256,
cpu_priority: "normal".to_string(),
+ oidc_enabled: false,
+ oidc_client_id: None,
+ oidc_client_secret: None,
+ oidc_issuer_url: None,
+ oidc_redirect_uri: None,
}
});
let db = Database::new(&config.database_url).await?;
@@ -126,6 +131,7 @@ async fn create_test_app_state() -> Result> {
webdav_scheduler: None,
source_scheduler: None,
queue_service,
+ oidc_client: None,
}))
}
diff --git a/tests/webdav_comprehensive_tests.rs b/tests/webdav_comprehensive_tests.rs
index 1bdfd4a..bc3ae67 100644
--- a/tests/webdav_comprehensive_tests.rs
+++ b/tests/webdav_comprehensive_tests.rs
@@ -340,6 +340,11 @@ fn test_webdav_scheduler_creation() {
max_file_size_mb: 50,
ocr_language: "eng".to_string(),
ocr_timeout_seconds: 300,
+ oidc_enabled: false,
+ oidc_client_id: None,
+ oidc_client_secret: None,
+ oidc_issuer_url: None,
+ oidc_redirect_uri: None,
};
// Note: This is a minimal test since we can't easily mock the database
diff --git a/tests/webdav_integration_tests.rs b/tests/webdav_integration_tests.rs
index 63f4a3a..c2fb351 100644
--- a/tests/webdav_integration_tests.rs
+++ b/tests/webdav_integration_tests.rs
@@ -93,6 +93,11 @@ async fn setup_test_app() -> (Router, Arc) {
max_file_size_mb: 50,
ocr_language: "eng".to_string(),
ocr_timeout_seconds: 300,
+ oidc_enabled: false,
+ oidc_client_id: None,
+ oidc_client_secret: None,
+ oidc_issuer_url: None,
+ oidc_redirect_uri: None,
};
// Use the environment-based database URL
@@ -106,6 +111,7 @@ async fn setup_test_app() -> (Router, Arc) {
webdav_scheduler: None,
source_scheduler: None,
queue_service,
+ oidc_client: None,
});
let app = Router::new()