Skip to main content

AirLibrary/Client/AirClient/
Authenticate.rs

1//! `AirClient::authenticate` - authenticates a user against the Air
2//! daemon's `AuthenticationService` and returns a session token on
3//! success.
4//!
5//! Translates the wire-level response:
6//!
7//! - `response.success == true` → `Ok(response.token)`
8//! - `response.success == false` → [`AirError::Authentication`] carrying
9//!   `response.error`
10//! - tonic transport / status failure → [`AirError::Network`]
11//!
12//! The caller passes a `request_id`; this lets log lines + traces from
13//! the daemon side be cross-referenced. Use
14//! [`crate::Client::AirServiceProvider::GenerateRequestID::Fn`] to mint
15//! one.
16
17use tonic::Request;
18
19use crate::{AirError, Client::AirClient::AirClient, Vine::Generated::air::AuthenticationRequest, dev_log};
20
21impl AirClient {
22	/// Authenticates a user with the Air daemon.
23	///
24	/// # Arguments
25	///
26	/// - `request_id` - opaque correlation id; see module docs.
27	/// - `username` / `password` - credentials.
28	/// - `provider` - authentication provider name (e.g. `"github"`,
29	///   `"gitlab"`, `"microsoft"`).
30	///
31	/// # Returns
32	///
33	/// On `Ok`, the session token string from the daemon.
34	pub async fn Authenticate(
35		&self,
36
37		request_id:String,
38
39		username:String,
40
41		password:String,
42
43		provider:String,
44	) -> Result<String, AirError> {
45		dev_log!(
46			"grpc",
47			"[AirClient] Authenticating user '{}' with provider '{}'",
48			username,
49			provider
50		);
51
52		let UsernameDisplay = username.clone();
53
54		let RequestPayload = AuthenticationRequest { request_id, username, password, provider };
55
56		let Client = self
57			.Client()
58			.ok_or_else(|| AirError::Network("Air client not initialized".to_string()))?;
59
60		let mut ClientGuard = Client.lock().await;
61
62		match ClientGuard.authenticate(Request::new(RequestPayload)).await {
63			Ok(Response) => {
64				let Response = Response.into_inner();
65
66				if Response.success {
67					dev_log!("grpc", "[AirClient] Authentication successful for user '{}'", UsernameDisplay);
68
69					Ok(Response.token)
70				} else {
71					dev_log!(
72						"grpc",
73						"error: [AirClient] Authentication failed for user '{}': {}",
74						UsernameDisplay,
75						Response.error
76					);
77
78					Err(AirError::Authentication(Response.error))
79				}
80			},
81
82			Err(Status) => {
83				dev_log!("grpc", "error: [AirClient] Authentication RPC error: {}", Status);
84
85				Err(AirError::Network(format!("Authentication RPC error: {}", Status)))
86			},
87		}
88	}
89}