1use std::future::Future;
2use uuid::Uuid;
3
4tokio::task_local! {
5 static CURRENT_USER_ID: String;
6 static CURRENT_WORKSPACE_ID: Uuid;
7}
8
9#[derive(Clone)]
10pub struct UserContext {
11 user_id: String,
12 workspace_id: Option<String>,
13}
14
15impl UserContext {
16 pub fn new(user_id: String) -> Self {
17 Self {
18 user_id,
19 workspace_id: None,
20 }
21 }
22
23 pub fn with_workspace(user_id: String, workspace_id: Option<String>) -> Self {
24 Self {
25 user_id,
26 workspace_id,
27 }
28 }
29
30 pub fn user_id(&self) -> String {
31 self.user_id.clone()
32 }
33
34 pub fn workspace_id(&self) -> Option<String> {
35 self.workspace_id.clone()
36 }
37}
38
39pub fn current_user_id() -> Option<String> {
40 CURRENT_USER_ID.try_with(|id| id.clone()).ok()
41}
42
43pub fn current_workspace_id() -> Option<Uuid> {
44 CURRENT_WORKSPACE_ID.try_with(|id| *id).ok()
45}
46
47pub async fn with_user_id<F, T>(user_id: String, fut: F) -> T
48where
49 F: Future<Output = T>,
50{
51 CURRENT_USER_ID.scope(user_id, fut).await
52}
53
54pub async fn with_user_and_workspace<F, T>(user_id: String, workspace_id: Option<Uuid>, fut: F) -> T
55where
56 F: Future<Output = T>,
57{
58 match workspace_id {
59 Some(ws_id) => {
60 CURRENT_USER_ID
61 .scope(user_id, CURRENT_WORKSPACE_ID.scope(ws_id, fut))
62 .await
63 }
64 None => CURRENT_USER_ID.scope(user_id, fut).await,
65 }
66}