systemprompt_api/services/static_content/
session.rs1use std::sync::Arc;
8
9use std::net::IpAddr;
10
11use anyhow::Result;
12use axum::http::HeaderMap;
13use systemprompt_identifiers::{ClientId, SessionId, SessionSource, UserId};
14use systemprompt_oauth::{CreateAnonymousSessionInput, SessionCreationService, validate_jwt_token};
15use systemprompt_runtime::AppContext;
16use systemprompt_security::TokenExtractor;
17use systemprompt_traits::ExtractSignals;
18use systemprompt_users::UserService;
19
20#[derive(Debug, Clone)]
21pub struct SessionInfo {
22 pub session_id: SessionId,
23 pub user_id: UserId,
24 pub is_new: bool,
25 pub jwt_token: Option<String>,
26}
27
28pub async fn ensure_session(
29 headers: &HeaderMap,
30 uri: Option<&http::Uri>,
31 caller_ip: Option<IpAddr>,
32 ctx: &AppContext,
33) -> Result<SessionInfo> {
34 let config = systemprompt_models::Config::get()?;
35
36 if let Ok(token) = TokenExtractor::browser_only().extract(headers)
37 && let Ok(claims) = validate_jwt_token(&token, &config.jwt_issuer, &config.jwt_audiences)
38 && let Some(session_id) = claims.session_id
39 {
40 return Ok(SessionInfo {
41 session_id: SessionId::new(session_id),
42 user_id: UserId::new(claims.sub),
43 is_new: false,
44 jwt_token: Some(token),
45 });
46 }
47
48 let user_service = UserService::new(ctx.db_pool())?;
49 let concrete = Arc::clone(ctx.analytics_service());
50 let analytics: Arc<dyn systemprompt_traits::AnalyticsProvider> = concrete;
51 let session_service = SessionCreationService::new(analytics, Arc::new(user_service));
52
53 let client_id = ClientId::new("sp_web");
54 let request_analytics = ctx
55 .analytics_service()
56 .extract_analytics(headers, ExtractSignals { uri, caller_ip });
57 let session_info = session_service
58 .create_anonymous_session(CreateAnonymousSessionInput {
59 analytics: &request_analytics,
60 client_id: &client_id,
61 session_source: SessionSource::Web,
62 })
63 .await?;
64
65 Ok(SessionInfo {
66 session_id: session_info.session_id,
67 user_id: session_info.user_id,
68 is_new: session_info.is_new,
69 jwt_token: Some(session_info.jwt_token),
70 })
71}