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