architect_api/auth/
grants.rs1use crate::symbology::MarketdataVenue;
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4
5pub static ALL: Grants = Grants::all();
6pub static NONE: Grants = Grants::none();
7
8#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
9pub struct Grants {
10 #[serde(default, skip_serializing_if = "Option::is_none")]
13 pub scoped: Option<bool>,
14 #[serde(default, skip_serializing_if = "Option::is_none")]
15 pub marketdata: Option<BoolOrList<MarketdataVenue>>,
16}
17
18impl Grants {
19 pub const fn all() -> Self {
20 Self { scoped: Some(false), marketdata: Some(BoolOrList::Bool(true)) }
21 }
22
23 pub const fn none() -> Self {
24 Self { scoped: Some(true), marketdata: None }
25 }
26
27 pub fn is_subset_of(&self, other: &Grants) -> bool {
28 if other.scoped.is_none() || other.scoped.is_some_and(|o| o == false) {
29 return true;
31 }
32 if self.scoped.is_none() || self.scoped.is_some_and(|s| s == false) {
34 return false;
36 }
37 match (&self.marketdata, &other.marketdata) {
39 (None, _) => {}
40 (Some(BoolOrList::Bool(false)), _) => {}
41 (Some(BoolOrList::List(_)), Some(BoolOrList::Bool(true))) => {}
42 (Some(BoolOrList::List(vs)), Some(BoolOrList::List(vs2))) => {
43 for v in vs {
44 if !vs2.contains(v) {
45 return false;
46 }
47 }
48 }
49 (Some(BoolOrList::Bool(true)), Some(BoolOrList::Bool(true))) => {}
50 _ => {
51 return false;
52 }
53 }
54 true
55 }
56
57 pub fn is_scoped(&self) -> bool {
58 self.scoped.unwrap_or(false)
59 }
60
61 pub fn allowed_to_trade(&self) -> bool {
62 if self.is_scoped() {
63 false
64 } else {
65 true
66 }
67 }
68
69 pub fn allowed_to_marketdata(&self, venue: &MarketdataVenue) -> bool {
70 if self.is_scoped() {
71 if let Some(marketdata) = &self.marketdata {
72 marketdata.includes(venue)
73 } else {
74 false
75 }
76 } else {
77 true
78 }
79 }
80}
81
82#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
83#[serde(untagged)]
84pub enum BoolOrList<T> {
85 Bool(bool),
86 List(Vec<T>),
87}
88
89impl<T> BoolOrList<T> {
90 pub fn is_all(&self) -> bool {
91 match self {
92 Self::Bool(b) => *b,
93 Self::List(_) => false,
94 }
95 }
96
97 pub fn is_none(&self) -> bool {
98 match self {
99 Self::Bool(b) => !*b,
100 Self::List(xs) => xs.is_empty(),
101 }
102 }
103}
104
105impl<T> BoolOrList<T>
106where
107 T: PartialEq,
108{
109 pub fn includes(&self, item: &T) -> bool {
110 match self {
111 Self::Bool(b) => *b,
112 Self::List(list) => list.contains(item),
113 }
114 }
115}