alibi_core/store/stateless/
device_codes.rs1use super::*;
3
4#[async_trait]
5impl DeviceCodeStore for StatelessStore {
6 async fn create_device_code(&self, input: CreateDeviceCode) -> AuthResult<DeviceCode> {
7 let device_code = DeviceCode {
8 id: uuid::Uuid::new_v4().to_string(),
9 device_code: input.device_code,
10 user_code: input.user_code,
11 user_id: input.user_id,
12 expires_at: input.expires_at,
13 status: input.status,
14 last_polled_at: input.last_polled_at,
15 polling_interval: input.polling_interval,
16 client_id: input.client_id,
17 scope: input.scope,
18 };
19 drop(
20 self.lock()?
21 .device_codes
22 .insert(device_code.id.clone(), device_code.clone()),
23 );
24 Ok(device_code)
25 }
26
27 async fn get_device_code_by_device_code(
28 &self,
29 device_code: &str,
30 ) -> AuthResult<Option<DeviceCode>> {
31 Ok(self
32 .lock()?
33 .device_codes
34 .values()
35 .find(|value| value.device_code == device_code)
36 .cloned())
37 }
38
39 async fn get_device_code_by_user_code(
40 &self,
41 user_code: &str,
42 ) -> AuthResult<Option<DeviceCode>> {
43 Ok(self
44 .lock()?
45 .device_codes
46 .values()
47 .find(|value| value.user_code == user_code)
48 .cloned())
49 }
50
51 async fn update_device_code(
52 &self,
53 id: &str,
54 update: UpdateDeviceCode,
55 ) -> AuthResult<DeviceCode> {
56 let mut state = self.lock()?;
57 let device_code = state
58 .device_codes
59 .get_mut(id)
60 .ok_or_else(|| AuthError::not_found("Device code not found"))?;
61
62 if let Some(status) = update.status {
63 device_code.status = status;
64 }
65 if let Some(user_id) = update.user_id {
66 device_code.user_id = user_id;
67 }
68 if let Some(last_polled_at) = update.last_polled_at {
69 device_code.last_polled_at = last_polled_at;
70 }
71
72 let locked_result = Ok(device_code.clone());
73 drop(state);
74 locked_result
75 }
76
77 async fn update_device_code_if_status(
78 &self,
79 id: &str,
80 current_status: &str,
81 update: UpdateDeviceCode,
82 ) -> AuthResult<bool> {
83 let mut state = self.lock()?;
84 let Some(device_code) = state.device_codes.get_mut(id) else {
85 return Ok(false);
86 };
87
88 if device_code.status != current_status {
89 return Ok(false);
90 }
91
92 if let Some(status) = update.status {
93 device_code.status = status;
94 }
95 if let Some(user_id) = update.user_id {
96 device_code.user_id = user_id;
97 }
98 if let Some(last_polled_at) = update.last_polled_at {
99 device_code.last_polled_at = last_polled_at;
100 }
101 drop(state);
102
103 Ok(true)
104 }
105
106 async fn claim_device_code(&self, id: &str, user_id: &str) -> AuthResult<bool> {
107 let mut state = self.lock()?;
108 let Some(device_code) = state.device_codes.get_mut(id) else {
109 return Ok(false);
110 };
111
112 if device_code.status != "pending" || device_code.user_id.is_some() {
113 return Ok(false);
114 }
115
116 device_code.user_id = Some(user_id.to_owned());
117 drop(state);
118
119 Ok(true)
120 }
121
122 async fn delete_device_code(&self, id: &str) -> AuthResult<()> {
123 drop(self.lock()?.device_codes.shift_remove(id));
124 Ok(())
125 }
126
127 async fn delete_device_code_if_status(&self, id: &str, status: &str) -> AuthResult<bool> {
128 let mut state = self.lock()?;
129 let should_delete = state
130 .device_codes
131 .get(id)
132 .is_some_and(|device_code| device_code.status == status);
133
134 if should_delete {
135 drop(state.device_codes.shift_remove(id));
136 }
137
138 let locked_result = Ok(should_delete);
139 drop(state);
140 locked_result
141 }
142}