this repo has no description
1use super::super::{DeviceData, OAuthError};
2use chrono::{DateTime, Utc};
3use sqlx::PgPool;
4
5pub struct DeviceAccountRow {
6 pub did: String,
7 pub handle: String,
8 pub email: Option<String>,
9 pub last_used_at: DateTime<Utc>,
10}
11
12pub async fn create_device(
13 pool: &PgPool,
14 device_id: &str,
15 data: &DeviceData,
16) -> Result<(), OAuthError> {
17 sqlx::query!(
18 r#"
19 INSERT INTO oauth_device (id, session_id, user_agent, ip_address, last_seen_at)
20 VALUES ($1, $2, $3, $4, $5)
21 "#,
22 device_id,
23 data.session_id,
24 data.user_agent,
25 data.ip_address,
26 data.last_seen_at,
27 )
28 .execute(pool)
29 .await?;
30 Ok(())
31}
32
33pub async fn get_device(pool: &PgPool, device_id: &str) -> Result<Option<DeviceData>, OAuthError> {
34 let row = sqlx::query!(
35 r#"
36 SELECT session_id, user_agent, ip_address, last_seen_at
37 FROM oauth_device
38 WHERE id = $1
39 "#,
40 device_id
41 )
42 .fetch_optional(pool)
43 .await?;
44 Ok(row.map(|r| DeviceData {
45 session_id: r.session_id,
46 user_agent: r.user_agent,
47 ip_address: r.ip_address,
48 last_seen_at: r.last_seen_at,
49 }))
50}
51
52pub async fn update_device_last_seen(pool: &PgPool, device_id: &str) -> Result<(), OAuthError> {
53 sqlx::query!(
54 r#"
55 UPDATE oauth_device
56 SET last_seen_at = NOW()
57 WHERE id = $1
58 "#,
59 device_id
60 )
61 .execute(pool)
62 .await?;
63 Ok(())
64}
65
66pub async fn delete_device(pool: &PgPool, device_id: &str) -> Result<(), OAuthError> {
67 sqlx::query!(
68 r#"
69 DELETE FROM oauth_device WHERE id = $1
70 "#,
71 device_id
72 )
73 .execute(pool)
74 .await?;
75 Ok(())
76}
77
78pub async fn upsert_account_device(
79 pool: &PgPool,
80 did: &str,
81 device_id: &str,
82) -> Result<(), OAuthError> {
83 sqlx::query!(
84 r#"
85 INSERT INTO oauth_account_device (did, device_id, created_at, updated_at)
86 VALUES ($1, $2, NOW(), NOW())
87 ON CONFLICT (did, device_id) DO UPDATE SET updated_at = NOW()
88 "#,
89 did,
90 device_id
91 )
92 .execute(pool)
93 .await?;
94 Ok(())
95}
96
97pub async fn get_device_accounts(
98 pool: &PgPool,
99 device_id: &str,
100) -> Result<Vec<DeviceAccountRow>, OAuthError> {
101 let rows = sqlx::query!(
102 r#"
103 SELECT u.did, u.handle, u.email, ad.updated_at as last_used_at
104 FROM oauth_account_device ad
105 JOIN users u ON u.did = ad.did
106 WHERE ad.device_id = $1
107 AND u.deactivated_at IS NULL
108 AND u.takedown_ref IS NULL
109 ORDER BY ad.updated_at DESC
110 "#,
111 device_id
112 )
113 .fetch_all(pool)
114 .await?;
115 Ok(rows
116 .into_iter()
117 .map(|r| DeviceAccountRow {
118 did: r.did,
119 handle: r.handle,
120 email: r.email,
121 last_used_at: r.last_used_at,
122 })
123 .collect())
124}
125
126pub async fn verify_account_on_device(
127 pool: &PgPool,
128 device_id: &str,
129 did: &str,
130) -> Result<bool, OAuthError> {
131 let row = sqlx::query!(
132 r#"
133 SELECT 1 as exists
134 FROM oauth_account_device ad
135 JOIN users u ON u.did = ad.did
136 WHERE ad.device_id = $1
137 AND ad.did = $2
138 AND u.deactivated_at IS NULL
139 AND u.takedown_ref IS NULL
140 "#,
141 device_id,
142 did
143 )
144 .fetch_optional(pool)
145 .await?;
146 Ok(row.is_some())
147}