1- use primitives:: WalletId ;
21use rocket:: Request ;
32use rocket:: http:: Status ;
43use rocket:: outcome:: Outcome :: { Error , Success } ;
5- use rocket:: request:: { FromRequest , Outcome } ;
6- use storage:: Database ;
4+ use rocket:: request:: Outcome ;
75use storage:: database:: devices:: DevicesStore ;
8- use storage:: database :: wallets :: WalletsStore ;
9- use storage:: models :: DeviceRow ;
6+ use storage:: models :: { DeviceRow , WalletRow } ;
7+ use storage:: { Database , DatabaseClient , WalletsRepository } ;
108
119use crate :: devices:: auth_config:: AuthConfig ;
1210use crate :: devices:: constants:: { DEVICE_ID_LENGTH , HEADER_DEVICE_ID , HEADER_WALLET_ID } ;
1311use crate :: devices:: error:: DeviceError ;
1412use crate :: devices:: signature:: { parse_auth_components, verify_request_signature} ;
1513use crate :: responders:: cache_error;
1614
17- fn auth_error_outcome < T > ( req : & Request < ' _ > , error : DeviceError , device_id : Option < & str > , wallet_id : Option < & str > ) -> Outcome < T , String > {
15+ pub ( super ) struct AuthResult {
16+ pub ( super ) device_id : String ,
17+ pub ( super ) wallet_id : Option < String > ,
18+ }
19+
20+ pub ( super ) fn auth_error_outcome < T > ( req : & Request < ' _ > , error : DeviceError , device_id : Option < & str > , wallet_id : Option < & str > ) -> Outcome < T , String > {
1821 let status = match error {
1922 DeviceError :: MissingHeader ( _)
2023 | DeviceError :: InvalidDeviceId
@@ -41,12 +44,7 @@ fn format_auth_error_message(error: &DeviceError, device_id: Option<&str>, walle
4144 message
4245}
4346
44- struct AuthResult {
45- device_id : String ,
46- wallet_id : Option < String > ,
47- }
48-
49- async fn authenticate < T > ( req : & Request < ' _ > ) -> Result < AuthResult , Outcome < T , String > > {
47+ pub ( super ) async fn authenticate < T > ( req : & Request < ' _ > ) -> Result < AuthResult , Outcome < T , String > > {
5048 let Success ( config) = req. guard :: < & rocket:: State < AuthConfig > > ( ) . await else {
5149 panic ! ( "AuthConfig not configured" ) ;
5250 } ;
@@ -86,84 +84,7 @@ async fn authenticate<T>(req: &Request<'_>) -> Result<AuthResult, Outcome<T, Str
8684 } )
8785}
8886
89- // Signature verified, no database check (for device registration)
90- pub struct VerifiedDeviceId ( pub String ) ;
91-
92- #[ rocket:: async_trait]
93- impl < ' r > FromRequest < ' r > for VerifiedDeviceId {
94- type Error = String ;
95-
96- async fn from_request ( req : & ' r Request < ' _ > ) -> Outcome < Self , String > {
97- match authenticate ( req) . await {
98- Ok ( auth) => Success ( VerifiedDeviceId ( auth. device_id ) ) ,
99- Err ( error) => error,
100- }
101- }
102- }
103-
104- // Signature verified + device exists in database
105- pub struct AuthenticatedDevice {
106- pub device_row : DeviceRow ,
107- }
108-
109- #[ rocket:: async_trait]
110- impl < ' r > FromRequest < ' r > for AuthenticatedDevice {
111- type Error = String ;
112-
113- async fn from_request ( req : & ' r Request < ' _ > ) -> Outcome < Self , String > {
114- let auth = match authenticate ( req) . await {
115- Ok ( auth) => auth,
116- Err ( error) => return error,
117- } ;
118-
119- let ( device_row, _) = match lookup_device ( req, & auth. device_id ) . await {
120- Ok ( result) => result,
121- Err ( error) => return error,
122- } ;
123-
124- Success ( AuthenticatedDevice { device_row } )
125- }
126- }
127-
128- // Signature verified + device and wallet exist in database
129- pub struct AuthenticatedDeviceWallet {
130- pub device_row : DeviceRow ,
131- pub wallet_id : i32 ,
132- pub wallet_identifier : WalletId ,
133- }
134-
135- #[ rocket:: async_trait]
136- impl < ' r > FromRequest < ' r > for AuthenticatedDeviceWallet {
137- type Error = String ;
138-
139- async fn from_request ( req : & ' r Request < ' _ > ) -> Outcome < Self , String > {
140- let auth = match authenticate ( req) . await {
141- Ok ( auth) => auth,
142- Err ( error) => return error,
143- } ;
144-
145- let Some ( wallet_id_str) = auth. wallet_id else {
146- return auth_error_outcome ( req, DeviceError :: MissingHeader ( HEADER_WALLET_ID ) , Some ( & auth. device_id ) , None ) ;
147- } ;
148-
149- let ( device_row, mut db_client) = match lookup_device ( req, & auth. device_id ) . await {
150- Ok ( result) => result,
151- Err ( error) => return error,
152- } ;
153-
154- let Ok ( wallet_row) = WalletsStore :: get_wallet ( & mut db_client, & wallet_id_str) else {
155- return auth_error_outcome ( req, DeviceError :: WalletNotFound , Some ( & auth. device_id ) , Some ( & wallet_id_str) ) ;
156- } ;
157-
158- Success ( AuthenticatedDeviceWallet {
159- device_row,
160- wallet_id : wallet_row. id ,
161- wallet_identifier : wallet_row. wallet_id . 0 ,
162- } )
163- }
164- }
165-
166- async fn lookup_device < T > ( req : & Request < ' _ > , device_id : & str ) -> Result < ( DeviceRow , storage:: DatabaseClient ) , Outcome < T , String > > {
87+ pub ( super ) async fn lookup_device < T > ( req : & Request < ' _ > , device_id : & str ) -> Result < ( DeviceRow , DatabaseClient ) , Outcome < T , String > > {
16788 let Success ( database) = req. guard :: < & rocket:: State < Database > > ( ) . await else {
16889 return Err ( auth_error_outcome ( req, DeviceError :: DatabaseUnavailable , Some ( device_id) , None ) ) ;
16990 } ;
@@ -179,6 +100,18 @@ async fn lookup_device<T>(req: &Request<'_>, device_id: &str) -> Result<(DeviceR
179100 Ok ( ( device_row, db_client) )
180101}
181102
103+ pub ( super ) async fn lookup_device_wallet < T > ( req : & Request < ' _ > , device_id : & str , wallet_id : & str ) -> Result < ( DeviceRow , WalletRow ) , Outcome < T , String > > {
104+ let ( device_row, mut db_client) = lookup_device ( req, device_id) . await ?;
105+
106+ let wallet_row = match db_client. get_wallet_by_device_and_identifier ( device_row. id , wallet_id) {
107+ Ok ( wallet_row) => wallet_row,
108+ Err ( error) if error. is_not_found ( ) => return Err ( auth_error_outcome ( req, DeviceError :: WalletNotFound , Some ( device_id) , Some ( wallet_id) ) ) ,
109+ Err ( _) => return Err ( auth_error_outcome ( req, DeviceError :: DatabaseError , Some ( device_id) , Some ( wallet_id) ) ) ,
110+ } ;
111+
112+ Ok ( ( device_row, wallet_row) )
113+ }
114+
182115#[ cfg( test) ]
183116mod tests {
184117 use super :: format_auth_error_message;
0 commit comments