Skip to content

Commit b67c125

Browse files
Wire U2M provider into Database::new_connection()\n\nTask ID: task-3.3-database-integration
1 parent cea68cd commit b67c125

File tree

6 files changed

+277
-236
lines changed

6 files changed

+277
-236
lines changed

rust/src/auth/oauth/cache.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,14 @@ use std::path::PathBuf;
2727

2828
/// Cache key used for generating the cache filename.
2929
/// This struct is serialized to JSON and then hashed with SHA-256 to produce a unique filename.
30-
#[allow(dead_code)] // Used in Phase 3 (U2M)
30+
3131
#[derive(Debug, Serialize, Deserialize)]
3232
struct CacheKey {
3333
host: String,
3434
client_id: String,
3535
scopes: Vec<String>,
3636
}
3737

38-
#[allow(dead_code)] // Used in Phase 3 (U2M)
3938
impl CacheKey {
4039
/// Creates a new cache key from the given parameters.
4140
fn new(host: &str, client_id: &str, scopes: &[String]) -> Self {
@@ -69,10 +68,8 @@ impl CacheKey {
6968
/// set to `0o600` (owner read/write only) for security.
7069
///
7170
/// Cache I/O errors are logged as warnings and never block authentication.
72-
#[allow(dead_code)] // Used in Phase 3 (U2M)
7371
pub(crate) struct TokenCache;
7472

75-
#[allow(dead_code)] // Used in Phase 3 (U2M)
7673
impl TokenCache {
7774
/// Returns the cache directory path.
7875
/// Location: `~/.config/databricks-adbc/oauth/`

rust/src/auth/oauth/callback.rs

Lines changed: 34 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -33,80 +33,20 @@ use tokio::sync::oneshot;
3333
/// HTML response sent to the browser after successful callback.
3434
const SUCCESS_HTML: &str = r#"<!DOCTYPE html>
3535
<html>
36-
<head>
37-
<title>Authentication Successful</title>
38-
<style>
39-
body {
40-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
41-
display: flex;
42-
justify-content: center;
43-
align-items: center;
44-
height: 100vh;
45-
margin: 0;
46-
background-color: #f5f5f5;
47-
}
48-
.message {
49-
text-align: center;
50-
padding: 2rem;
51-
background: white;
52-
border-radius: 8px;
53-
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
54-
}
55-
h1 {
56-
color: #2e7d32;
57-
margin: 0 0 1rem 0;
58-
}
59-
p {
60-
color: #666;
61-
margin: 0;
62-
}
63-
</style>
64-
</head>
36+
<head><title>Authentication Successful</title></head>
6537
<body>
66-
<div class="message">
67-
<h1>✓ Authentication Successful</h1>
68-
<p>You can close this tab and return to your application.</p>
69-
</div>
38+
<h1>Authentication Successful</h1>
39+
<p>You can close this tab and return to your application.</p>
7040
</body>
7141
</html>"#;
7242

7343
/// HTML response sent to the browser when an error occurs.
7444
const ERROR_HTML: &str = r#"<!DOCTYPE html>
7545
<html>
76-
<head>
77-
<title>Authentication Error</title>
78-
<style>
79-
body {
80-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
81-
display: flex;
82-
justify-content: center;
83-
align-items: center;
84-
height: 100vh;
85-
margin: 0;
86-
background-color: #f5f5f5;
87-
}
88-
.message {
89-
text-align: center;
90-
padding: 2rem;
91-
background: white;
92-
border-radius: 8px;
93-
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
94-
}
95-
h1 {
96-
color: #c62828;
97-
margin: 0 0 1rem 0;
98-
}
99-
p {
100-
color: #666;
101-
margin: 0;
102-
}
103-
</style>
104-
</head>
46+
<head><title>Authentication Error</title></head>
10547
<body>
106-
<div class="message">
107-
<h1>✗ Authentication Error</h1>
108-
<p>An error occurred during authentication. You can close this tab and try again.</p>
109-
</div>
48+
<h1>Authentication Error</h1>
49+
<p>An error occurred during authentication. You can close this tab and try again.</p>
11050
</body>
11151
</html>"#;
11252

@@ -157,6 +97,15 @@ pub struct CallbackServer {
15797
server_handle: Option<tokio::task::JoinHandle<()>>,
15898
}
15999

100+
impl Drop for CallbackServer {
101+
fn drop(&mut self) {
102+
// Abort the server task if it's still running (e.g., wait_for_code was never called)
103+
if let Some(handle) = self.server_handle.take() {
104+
handle.abort();
105+
}
106+
}
107+
}
108+
160109
impl CallbackServer {
161110
/// Creates a new callback server listening on the specified port.
162111
///
@@ -496,7 +445,7 @@ mod tests {
496445

497446
// Read the response
498447
let mut response = vec![0u8; 4096];
499-
stream.read(&mut response).await.ok();
448+
let _ = stream.read(&mut response).await;
500449
});
501450

502451
// Wait for callback
@@ -533,7 +482,7 @@ mod tests {
533482
stream.flush().await.ok();
534483

535484
let mut response = vec![0u8; 4096];
536-
stream.read(&mut response).await.ok();
485+
let _ = stream.read(&mut response).await;
537486
});
538487

539488
// Wait for callback - should fail due to state mismatch
@@ -668,9 +617,24 @@ mod tests {
668617

669618
#[tokio::test]
670619
async fn test_redirect_uri_format() {
671-
let server = CallbackServer::new(8020)
620+
// Use port 0 to let the OS assign an available port, avoiding conflicts
621+
let server = CallbackServer::new(0)
672622
.await
673623
.expect("Failed to create server");
674-
assert_eq!(server.redirect_uri(), "http://localhost:8020/callback");
624+
let uri = server.redirect_uri();
625+
assert!(
626+
uri.starts_with("http://localhost:"),
627+
"Expected URI starting with http://localhost:, got: {}",
628+
uri
629+
);
630+
// Verify the port is a valid non-zero number
631+
let port: u16 = uri
632+
.strip_prefix("http://localhost:")
633+
.unwrap()
634+
.strip_suffix("/callback")
635+
.unwrap_or_else(|| uri.strip_prefix("http://localhost:").unwrap())
636+
.parse()
637+
.unwrap();
638+
assert!(port > 0, "Expected a non-zero port, got: {}", port);
675639
}
676640
}

0 commit comments

Comments
 (0)