alibi_core/wire/
session.rs1use crate::AuthSession;
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize, Serializer};
4use std::borrow::Cow;
5#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
7pub struct SessionView {
8 pub id: String,
9 #[serde(rename = "expiresAt")]
10 pub expires_at: DateTime<Utc>,
11 pub token: String,
12 #[serde(rename = "createdAt")]
13 pub created_at: DateTime<Utc>,
14 #[serde(rename = "updatedAt")]
15 pub updated_at: DateTime<Utc>,
16 #[serde(rename = "ipAddress")]
17 pub ip_address: Option<String>,
18 #[serde(rename = "userAgent")]
19 pub user_agent: Option<String>,
20 #[serde(rename = "userId")]
21 pub user_id: String,
22 #[serde(rename = "impersonatedBy", default)]
23 pub impersonated_by: Option<String>,
24 #[serde(rename = "activeOrganizationId", default)]
25 pub active_organization_id: Option<String>,
26 #[serde(rename = "activeTeamId", default)]
27 pub active_team_id: Option<String>,
28 #[serde(
29 flatten,
30 default,
31 deserialize_with = "crate::utils::json::deserialize_btree_map"
32 )]
33 pub extension_fields: std::collections::BTreeMap<String, serde_json::Value>,
34 #[serde(skip)]
35 pub omitted_fields: std::collections::BTreeSet<String>,
36}
37
38impl Serialize for SessionView {
39 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
40 use serde::ser::SerializeMap;
41 let mut map = serializer.serialize_map(None)?;
42 macro_rules! entry {
43 ($name:literal, $value:expr) => {
44 if !self.omitted_fields.contains($name) {
45 map.serialize_entry($name, $value)?;
46 }
47 };
48 }
49 entry!("id", &self.id);
50 entry!(
51 "expiresAt",
52 &crate::utils::datetime::json_date_millis(self.expires_at.timestamp_millis())
53 );
54 entry!("token", &self.token);
55 entry!(
56 "createdAt",
57 &crate::utils::datetime::json_date_millis(self.created_at.timestamp_millis())
58 );
59 entry!(
60 "updatedAt",
61 &crate::utils::datetime::json_date_millis(self.updated_at.timestamp_millis())
62 );
63 entry!("ipAddress", &self.ip_address);
64 entry!("userAgent", &self.user_agent);
65 entry!("userId", &self.user_id);
66 if let Some(value) = &self.impersonated_by {
67 entry!("impersonatedBy", value);
68 }
69 if let Some(value) = &self.active_organization_id {
70 entry!("activeOrganizationId", value);
71 }
72 if let Some(value) = &self.active_team_id {
73 entry!("activeTeamId", value);
74 }
75 for (name, value) in &self.extension_fields {
76 if !self.omitted_fields.contains(name) {
77 map.serialize_entry(name, value)?;
78 }
79 }
80 map.end()
81 }
82}
83
84impl<T: AuthSession> From<&T> for SessionView {
85 fn from(session: &T) -> Self {
86 Self {
87 id: session.id().into_owned(),
88 expires_at: session.expires_at(),
89 token: session.token().to_owned(),
90 created_at: session.created_at(),
91 updated_at: session.updated_at(),
92 ip_address: session.ip_address().map(str::to_owned),
93 user_agent: session.user_agent().map(str::to_owned),
94 user_id: session.user_id().into_owned(),
95 impersonated_by: session.impersonated_by().map(str::to_owned),
96 active_organization_id: session.active_organization_id().map(str::to_owned),
97 active_team_id: session.active_team_id().map(str::to_owned),
98 extension_fields: session.additional_fields().into_iter().collect(),
99 omitted_fields: std::collections::BTreeSet::default(),
100 }
101 }
102}
103
104impl AuthSession for SessionView {
105 fn retained_session_view(&self) -> Option<&SessionView> {
106 Some(self)
107 }
108 fn additional_fields(&self) -> serde_json::Map<String, serde_json::Value> {
109 self.extension_fields.clone().into_iter().collect()
110 }
111 fn id(&self) -> Cow<'_, str> {
112 Cow::Borrowed(&self.id)
113 }
114 fn expires_at(&self) -> DateTime<Utc> {
115 self.expires_at
116 }
117 fn token(&self) -> &str {
118 &self.token
119 }
120 fn created_at(&self) -> DateTime<Utc> {
121 self.created_at
122 }
123 fn updated_at(&self) -> DateTime<Utc> {
124 self.updated_at
125 }
126 fn ip_address(&self) -> Option<&str> {
127 self.ip_address.as_deref()
128 }
129 fn user_agent(&self) -> Option<&str> {
130 self.user_agent.as_deref()
131 }
132 fn user_id(&self) -> Cow<'_, str> {
133 Cow::Borrowed(&self.user_id)
134 }
135 fn impersonated_by(&self) -> Option<&str> {
136 self.impersonated_by.as_deref()
137 }
138 fn active_organization_id(&self) -> Option<&str> {
139 self.active_organization_id.as_deref()
140 }
141 fn active_team_id(&self) -> Option<&str> {
142 self.active_team_id.as_deref()
143 }
144}