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