1use std::sync::{
2 atomic::{AtomicU64, Ordering},
3 Arc,
4};
5
6use soma_application::{ExecutionContext, SomaApplication};
7use soma_domain::{AuthorizationMode, Principal, RequestId, ScopeSet, Surface};
8
9#[cfg(test)]
10#[path = "state_tests.rs"]
11mod tests;
12
13#[derive(Clone)]
16pub struct PaletteState {
17 application: Arc<SomaApplication>,
18 authorization_mode: AuthorizationMode,
19}
20
21impl PaletteState {
22 #[must_use]
23 pub fn new(application: Arc<SomaApplication>, authorization_mode: AuthorizationMode) -> Self {
24 Self {
25 application,
26 authorization_mode,
27 }
28 }
29
30 #[must_use]
31 pub fn application(&self) -> &SomaApplication {
32 self.application.as_ref()
33 }
34
35 #[must_use]
39 pub fn execution_context(&self, subject: Option<&str>, scopes: &[String]) -> ExecutionContext {
40 ExecutionContext {
41 principal: subject
42 .map(|subject| Principal::new(subject, ScopeSet::new(scopes.iter().cloned()))),
43 authorization_mode: self.authorization_mode,
44 surface: Surface::Palette,
45 trace: None,
46 destructive_confirmation: Default::default(),
47 response_limit: None,
48 request_id: next_request_id(),
49 }
50 }
51}
52
53fn next_request_id() -> RequestId {
54 static REQUEST_SEQUENCE: AtomicU64 = AtomicU64::new(1);
55 let sequence = REQUEST_SEQUENCE.fetch_add(1, Ordering::Relaxed);
56 RequestId::new(format!("palette-{}-{sequence}", std::process::id()))
57 .expect("generated palette request ids are valid")
58}