jsonprooftoken/jpt/
claims.rs1use std::iter::zip;
16
17use indexmap::IndexMap;
18use json_unflattening::{flattening::flatten, unflattening::unflatten};
19use serde::{Deserialize, Serialize};
20use serde_json::{json, Map, Value};
21
22use super::payloads::Payloads;
23
24#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
25pub struct Claims(pub Vec<String>);
26
27impl Claims {
28 pub fn get_claim_index(&self, name: String) -> Option<usize> {
29 self.0.iter().position(|x| *x == name)
30 }
31}
32
33#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
34pub struct CustomValue {
35 value: Value,
36 #[serde(skip_serializing)]
37 flattening: bool,
38}
39
40#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
44pub struct JptClaims {
45 #[serde(skip_serializing_if = "Option::is_none")]
49 pub iss: Option<String>,
50 #[serde(skip_serializing_if = "Option::is_none")]
52 pub sub: Option<String>,
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub exp: Option<i64>,
56 #[serde(skip_serializing_if = "Option::is_none")]
58 pub nbf: Option<i64>,
59 #[serde(skip_serializing_if = "Option::is_none")]
61 pub iat: Option<i64>,
62 #[serde(skip_serializing_if = "Option::is_none")]
64 pub jti: Option<String>,
65 #[serde(flatten)]
67 pub custom: IndexMap<String, Value>,
68}
69
70impl JptClaims {
71 pub fn new() -> Self {
72 Self {
73 iss: None,
74 sub: None,
75 exp: None,
76 nbf: None,
77 iat: None,
78 jti: None,
79 custom: IndexMap::new(),
80 }
81 }
82
83 pub fn set_iss(&mut self, value: String) {
84 self.iss = Some(value);
85 }
86
87 pub fn set_sub(&mut self, value: String) {
88 self.sub = Some(value);
89 }
90
91 pub fn set_exp(&mut self, value: i64) {
92 self.exp = Some(value);
93 }
94
95 pub fn set_nbf(&mut self, value: i64) {
96 self.nbf = Some(value);
97 }
98
99 pub fn set_iat(&mut self, value: i64) {
100 self.iat = Some(value);
101 }
102
103 pub fn set_jti(&mut self, value: String) {
104 self.jti = Some(value);
105 }
106
107 pub fn set_claim<T: Serialize>(&mut self, claim: Option<&str>, value: T, flattened: bool) {
108 let serde_value = serde_json::to_value(value).unwrap();
109 if !serde_value.is_object() {
110 self.custom
111 .insert(claim.unwrap_or("").to_string(), serde_value);
112 } else {
113 if flattened {
114 let v = match claim {
115 Some(c) => json!({c: serde_value}),
116 None => serde_value,
117 };
118 self.custom.extend(flatten(&v).unwrap());
119 } else {
120 self.custom
121 .insert(claim.unwrap_or("").to_string(), serde_value);
122 }
123 };
124 }
125
126 pub fn get_claim(&self, claim: &str) -> Option<&Value> {
127 self.custom.get(claim)
128 }
129
130 pub fn update_claim_and_return_older(&mut self, claim: &str, value: Value) -> Option<Value> {
131 self.custom.insert(claim.to_owned(), value)
132 }
133
134 pub fn get_claims_and_payloads(&self) -> (Claims, Payloads) {
136 let jptclaims_json_value = serde_json::to_value(self).unwrap();
137
138 let claims_payloads_pairs = jptclaims_json_value.as_object().unwrap().to_owned();
139
140 let (keys, values): (Vec<String>, Vec<Value>) =
141 claims_payloads_pairs.to_owned().into_iter().unzip();
142
143 (Claims(keys), Payloads::new_from_values(values))
144 }
145
146 pub fn from_claims_and_payloads(claims: &Claims, payloads: &Payloads) -> Self {
148 let zip: Map<String, Value> = zip(claims.0.clone(), payloads.get_values()).collect();
149 let unflat = unflatten(&zip).unwrap();
150 let jpt_claims: Self = serde_json::from_value(unflat).unwrap();
151
152 jpt_claims
153 }
154}