1use rusqlite::{OptionalExtension, params};
5
6use crate::error::AuthError;
7use crate::types::{BrowserLoginStateRow, BrowserSessionRow, NativeAuthorizationResultRow};
8use crate::util::now_unix;
9
10use super::sqlite_rows::{
11 row_to_browser_login_state, row_to_browser_session, row_to_native_authorization_result,
12};
13use super::{SqliteStore, sqlite_error};
14
15impl SqliteStore {
16 pub async fn upsert_browser_session(
17 &self,
18 session: BrowserSessionRow,
19 ) -> Result<(), AuthError> {
20 self.with_conn(move |conn| {
21 conn.execute(
22 "INSERT INTO browser_sessions (
23 session_id, subject, email, csrf_token, created_at, expires_at
24 ) VALUES (?1, ?2, ?3, ?4, ?5, ?6)
25 ON CONFLICT(session_id) DO UPDATE SET
26 subject = excluded.subject,
27 email = excluded.email,
28 csrf_token = excluded.csrf_token,
29 created_at = excluded.created_at,
30 expires_at = excluded.expires_at",
31 params![
32 session.session_id,
33 session.subject,
34 session.email,
35 session.csrf_token,
36 session.created_at,
37 session.expires_at,
38 ],
39 )
40 .map_err(sqlite_error)?;
41 Ok(())
42 })
43 .await
44 }
45
46 pub async fn find_browser_session(
47 &self,
48 session_id: &str,
49 ) -> Result<Option<BrowserSessionRow>, AuthError> {
50 let session_id = session_id.to_string();
51 let now = now_unix();
52 self.with_conn(move |conn| {
53 conn.query_row(
54 "SELECT session_id, subject, email, csrf_token, created_at, expires_at
55 FROM browser_sessions
56 WHERE session_id = ?1
57 AND expires_at > ?2",
58 params![session_id, now],
59 row_to_browser_session,
60 )
61 .optional()
62 .map_err(sqlite_error)
63 })
64 .await
65 }
66
67 pub async fn revoke_browser_session(&self, session_id: &str) -> Result<(), AuthError> {
68 let session_id = session_id.to_string();
69 self.with_conn(move |conn| {
70 conn.execute(
71 "DELETE FROM browser_sessions WHERE session_id = ?1",
72 params![session_id],
73 )
74 .map_err(sqlite_error)?;
75 Ok(())
76 })
77 .await
78 }
79
80 pub async fn insert_browser_login_state(
81 &self,
82 login: BrowserLoginStateRow,
83 ) -> Result<(), AuthError> {
84 self.with_conn(move |conn| {
85 conn.execute(
86 "INSERT INTO browser_login_states (
87 state, return_to, provider_code_verifier, created_at, expires_at, provider
88 ) VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
89 params![
90 login.state,
91 login.return_to,
92 login.provider_code_verifier,
93 login.created_at,
94 login.expires_at,
95 login.provider,
96 ],
97 )
98 .map_err(sqlite_error)?;
99 Ok(())
100 })
101 .await
102 }
103
104 pub async fn take_browser_login_state(
105 &self,
106 state: &str,
107 ) -> Result<Option<BrowserLoginStateRow>, AuthError> {
108 let state = state.to_string();
109 let now = now_unix();
110 self.with_conn(move |conn| {
111 conn.query_row(
112 "DELETE FROM browser_login_states
113 WHERE state = ?1
114 AND expires_at > ?2
115 RETURNING state, return_to, provider_code_verifier, created_at, expires_at, provider",
116 params![state, now],
117 row_to_browser_login_state,
118 )
119 .optional()
120 .map_err(sqlite_error)
121 })
122 .await
123 }
124
125 pub async fn insert_native_authorization_result(
135 &self,
136 result: NativeAuthorizationResultRow,
137 ) -> Result<(), AuthError> {
138 self.with_conn(move |conn| {
139 conn.execute(
140 "INSERT INTO native_authorization_results (state, code, created_at, expires_at)
141 VALUES (?1, ?2, ?3, ?4)
142 ON CONFLICT(state) DO UPDATE SET
143 code = excluded.code,
144 created_at = excluded.created_at,
145 expires_at = excluded.expires_at",
146 params![
147 result.state,
148 result.code,
149 result.created_at,
150 result.expires_at,
151 ],
152 )
153 .map_err(sqlite_error)?;
154 Ok(())
155 })
156 .await
157 }
158
159 pub async fn take_native_authorization_result(
161 &self,
162 state: &str,
163 ) -> Result<Option<NativeAuthorizationResultRow>, AuthError> {
164 let state = state.to_string();
165 let now = now_unix();
166 self.with_conn(move |conn| {
167 conn.query_row(
168 "DELETE FROM native_authorization_results
169 WHERE state = ?1
170 AND expires_at > ?2
171 RETURNING state, code, created_at, expires_at",
172 params![state, now],
173 row_to_native_authorization_result,
174 )
175 .optional()
176 .map_err(sqlite_error)
177 })
178 .await
179 }
180}