this repo has no description
1use chrono::{DateTime, Utc}; 2use sqlx::PgPool; 3use super::super::{DeviceData, OAuthError}; 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( 53 pool: &PgPool, 54 device_id: &str, 55) -> Result<(), OAuthError> { 56 sqlx::query!( 57 r#" 58 UPDATE oauth_device 59 SET last_seen_at = NOW() 60 WHERE id = $1 61 "#, 62 device_id 63 ) 64 .execute(pool) 65 .await?; 66 Ok(()) 67} 68 69pub async fn delete_device(pool: &PgPool, device_id: &str) -> Result<(), OAuthError> { 70 sqlx::query!( 71 r#" 72 DELETE FROM oauth_device WHERE id = $1 73 "#, 74 device_id 75 ) 76 .execute(pool) 77 .await?; 78 Ok(()) 79} 80 81pub async fn upsert_account_device( 82 pool: &PgPool, 83 did: &str, 84 device_id: &str, 85) -> Result<(), OAuthError> { 86 sqlx::query!( 87 r#" 88 INSERT INTO oauth_account_device (did, device_id, created_at, updated_at) 89 VALUES ($1, $2, NOW(), NOW()) 90 ON CONFLICT (did, device_id) DO UPDATE SET updated_at = NOW() 91 "#, 92 did, 93 device_id 94 ) 95 .execute(pool) 96 .await?; 97 Ok(()) 98} 99 100pub async fn get_device_accounts( 101 pool: &PgPool, 102 device_id: &str, 103) -> Result<Vec<DeviceAccountRow>, OAuthError> { 104 let rows = sqlx::query!( 105 r#" 106 SELECT u.did, u.handle, u.email, ad.updated_at as last_used_at 107 FROM oauth_account_device ad 108 JOIN users u ON u.did = ad.did 109 WHERE ad.device_id = $1 110 AND u.deactivated_at IS NULL 111 AND u.takedown_ref IS NULL 112 ORDER BY ad.updated_at DESC 113 "#, 114 device_id 115 ) 116 .fetch_all(pool) 117 .await?; 118 Ok(rows 119 .into_iter() 120 .map(|r| DeviceAccountRow { 121 did: r.did, 122 handle: r.handle, 123 email: r.email, 124 last_used_at: r.last_used_at, 125 }) 126 .collect()) 127} 128 129pub async fn verify_account_on_device( 130 pool: &PgPool, 131 device_id: &str, 132 did: &str, 133) -> Result<bool, OAuthError> { 134 let row = sqlx::query!( 135 r#" 136 SELECT 1 as exists 137 FROM oauth_account_device ad 138 JOIN users u ON u.did = ad.did 139 WHERE ad.device_id = $1 140 AND ad.did = $2 141 AND u.deactivated_at IS NULL 142 AND u.takedown_ref IS NULL 143 "#, 144 device_id, 145 did 146 ) 147 .fetch_optional(pool) 148 .await?; 149 Ok(row.is_some()) 150}