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