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