1
+ use crate :: core:: module:: State ;
2
+ use crate :: domain:: module_state:: ModuleState ;
1
3
use crate :: domain:: mpsc_handle:: one_shot;
2
4
use crate :: domain:: node:: Manager ;
3
5
use crate :: domain:: oauth2:: extra_parameters:: { ExtraParameters , WithExtraParametersExt } ;
4
6
use crate :: domain:: oauth2:: token:: { BasicTokenResponseExt , Token , TokenExt , TokenStatus } ;
5
- use crate :: domain:: oauth2:: ApplicationSecret ;
7
+ use crate :: domain:: oauth2:: { ApplicationSecret , Config , PersistableConfig } ;
8
+ use crate :: integration:: google:: auth:: ConfigQuery ;
6
9
use crate :: server:: Event :: Redirect ;
7
10
use crate :: server:: { Code , Event , WebEventChannelHandle } ;
8
11
use crate :: static_init:: error:: Error :: FailedAfterRetries ;
@@ -18,7 +21,9 @@ use oauth2::{
18
21
RefreshToken , Scope ,
19
22
} ;
20
23
use std:: future:: Future ;
24
+ use std:: io;
21
25
use std:: path:: { Path , PathBuf } ;
26
+ use std:: pin:: Pin ;
22
27
use std:: sync:: Arc ;
23
28
use tokio:: fs;
24
29
use tokio:: sync:: broadcast:: error:: RecvError ;
@@ -28,18 +33,28 @@ use tokio::time::sleep;
28
33
use Error :: Oauth2CsrfMismatch ;
29
34
use Event :: Oauth2Code ;
30
35
31
- pub trait Client : Clone + Send + Sized + Sync + ' static {
36
+ pub trait Client : Send + Sync + ' static {
32
37
fn new (
33
38
application_secret : ApplicationSecret ,
34
39
extra_parameters : & ExtraParameters ,
35
40
manager : & Manager ,
36
41
token_path : & Path ,
37
42
web_channel_handle : & WebEventChannelHandle ,
38
- ) -> Self ;
39
- fn get_token (
40
- & self ,
41
- scopes : & [ & str ] ,
42
- ) -> impl Future < Output = Result < AccessToken , Error > > + Send + Sync ;
43
+ ) -> Pin < Box < Self > >
44
+ where
45
+ Self : Sized + ' static ;
46
+ fn get_auth_config < ' async_trait > (
47
+ name : & ' async_trait str ,
48
+ ) -> Pin < Box < dyn Future < Output = Result < impl Config , io:: Error > > + Send + ' async_trait > >
49
+ where
50
+ Self : Sized + Sync + ' async_trait ;
51
+ fn duplicate ( & self ) -> Pin < Box < dyn Client > > ;
52
+ fn get_token < ' async_trait > (
53
+ & ' async_trait self ,
54
+ scopes : & ' async_trait [ & ' async_trait str ] ,
55
+ ) -> Pin < Box < dyn Future < Output = Result < AccessToken , Error > > + Send + ' async_trait > >
56
+ where
57
+ Self : Sync + ' async_trait ;
43
58
}
44
59
45
60
#[ derive( Clone ) ]
@@ -60,31 +75,62 @@ impl Client for BasicClientImpl {
60
75
manager : & Manager ,
61
76
token_path : & Path ,
62
77
web_channel_handle : & WebEventChannelHandle ,
63
- ) -> Self {
78
+ ) -> Pin < Box < Self > > {
64
79
let basic_client = application_secret. to_client ( ) ;
65
- Self {
80
+ Box :: pin ( Self {
66
81
basic_client,
67
82
extra_parameters : extra_parameters. clone ( ) ,
68
83
manager : manager. clone ( ) ,
69
84
retry_max : 9 ,
70
85
retry_period : std:: time:: Duration :: from_secs ( 2 ) ,
71
86
token_path : token_path. to_owned ( ) ,
72
87
web_channel_handle : web_channel_handle. clone ( ) ,
73
- }
88
+ } )
74
89
}
75
90
76
- async fn get_token ( & self , scopes : & [ & str ] ) -> Result < AccessToken , Error > {
77
- match self . get_token_status_from_file ( ) . await {
78
- TokenStatus :: Ok ( token) => Ok ( token. access_token ( ) . clone ( ) ) ,
79
- TokenStatus :: Expired ( refresh_token) => self
80
- . refresh_token ( & refresh_token)
81
- . await
82
- . map ( |token| token. access_token ( ) . clone ( ) ) ,
83
- TokenStatus :: Absent => self . retrieve_token ( scopes) . await . map ( |token| {
84
- debug ! ( "Token retrieved: {:?}" , token) ;
85
- token. access_token ( ) . clone ( )
86
- } ) ,
87
- }
91
+ fn get_auth_config < ' async_trait > (
92
+ name : & ' async_trait str ,
93
+ ) -> Pin < Box < dyn Future < Output = Result < impl Config , io:: Error > > + Send + ' async_trait > >
94
+ where
95
+ Self : Sized + Sync + ' async_trait ,
96
+ {
97
+ Box :: pin (
98
+ async move { Ok ( ConfigQuery :: read_config ( & State :: path_for_name ( name) . await ?) . await ?) } ,
99
+ )
100
+ }
101
+
102
+ fn duplicate ( & self ) -> Pin < Box < dyn Client > > {
103
+ Box :: pin ( Self {
104
+ basic_client : self . basic_client . clone ( ) ,
105
+ extra_parameters : self . extra_parameters . clone ( ) ,
106
+ manager : self . manager . clone ( ) ,
107
+ retry_max : self . retry_max ,
108
+ retry_period : self . retry_period ,
109
+ token_path : self . token_path . to_owned ( ) ,
110
+ web_channel_handle : self . web_channel_handle . clone ( ) ,
111
+ } )
112
+ }
113
+
114
+ fn get_token < ' async_trait > (
115
+ & ' async_trait self ,
116
+ scopes : & ' async_trait [ & ' async_trait str ] ,
117
+ ) -> Pin < Box < dyn Future < Output = Result < AccessToken , Error > > + Send + ' async_trait > >
118
+ where
119
+ Self : Sync + ' async_trait ,
120
+ {
121
+ Box :: pin ( async move {
122
+ match self . get_token_status_from_file ( ) . await {
123
+ TokenStatus :: Ok ( token) => Ok ( token. access_token ( ) . clone ( ) ) ,
124
+ TokenStatus :: Expired ( refresh_token) => self
125
+ . refresh_token ( & refresh_token)
126
+ . await
127
+ . map ( |token| token. access_token ( ) . clone ( ) ) ,
128
+ TokenStatus :: Absent => self . retrieve_token ( scopes) . await . map ( |token| {
129
+ debug ! ( "Token retrieved: {:?}" , token) ;
130
+ token. access_token ( ) . clone ( )
131
+ } ) ,
132
+ }
133
+ } )
88
134
}
89
135
}
90
136
@@ -300,6 +346,16 @@ impl BasicClientImpl {
300
346
pub mod tests {
301
347
use super :: * ;
302
348
349
+ mod send_and_sync {
350
+ use super :: * ;
351
+ use crate :: assert_is_send_and_sync;
352
+
353
+ #[ test]
354
+ fn basic_client_impl_is_send_and_sync ( ) {
355
+ assert_is_send_and_sync ! ( BasicClientImpl ) ;
356
+ }
357
+ }
358
+
303
359
mod make_redirect_url {
304
360
use super :: * ;
305
361
use crate :: domain:: config:: tests:: test_config;
@@ -381,12 +437,61 @@ pub mod tests {
381
437
}
382
438
383
439
mod access_token {
440
+ use crate :: assert_is_send_and_sync;
384
441
use oauth2:: AccessToken ;
385
442
386
443
#[ test]
387
444
fn test_is_send_and_sync ( ) {
388
- fn is_send_and_sync < T : Send + Sync > ( ) { }
389
- is_send_and_sync :: < AccessToken > ( ) ;
445
+ assert_is_send_and_sync ! ( AccessToken ) ;
446
+ }
447
+ }
448
+
449
+ mod get_auth_config {
450
+ use super :: * ;
451
+ use crate :: domain:: config:: Config as CoreConfig ;
452
+ use crate :: domain:: module_state:: NamedModule ;
453
+ use crate :: domain:: oauth2:: config:: ConfigProperties ;
454
+
455
+ pub struct NamedType ;
456
+
457
+ impl NamedModule for NamedType {
458
+ fn name ( ) -> & ' static str {
459
+ "test"
460
+ }
461
+ }
462
+
463
+ impl NamedType {
464
+ async fn typed_test < T : Client > ( & self ) -> ApplicationSecret {
465
+ task:: spawn ( async move {
466
+ let config = T :: get_auth_config ( "name" ) . await . unwrap ( ) ;
467
+ assert_eq ! ( config. auth_uri( ) , "auth_uri" ) ;
468
+ assert_eq ! (
469
+ config. auth_provider_x509_cert_url( ) ,
470
+ "auth_provider_x509_cert_url"
471
+ ) ;
472
+ assert_eq ! ( config. client_email( ) , Some ( "client_email" ) ) ;
473
+ assert_eq ! ( config. client_id( ) , "client_id" ) ;
474
+ assert_eq ! ( config. client_secret( ) , "client_secret" ) ;
475
+ assert_eq ! ( config. client_x509_cert_url( ) , Some ( "client_x509_cert_url" ) ) ;
476
+ assert_eq ! ( config. project_id( ) , "project_id" ) ;
477
+ assert_eq ! ( config. redirect_uris( ) , & vec![ "redirect_uris" . to_string( ) ] ) ;
478
+ assert_eq ! ( config. token_uri( ) , "token_uri" ) ;
479
+ let core_config = CoreConfig :: with_all_properties ( None , None , None , None ) ;
480
+ let app_secret = config. to_application_secret ( & core_config) ;
481
+ app_secret
482
+ } )
483
+ . await
484
+ . unwrap ( )
485
+ }
486
+ }
487
+
488
+ // Trying to reproduce
489
+ // lifetime bound not satisfied
490
+ // Note: this is a known limitation that will be removed in the future (see issue #100013 <https:// github. com/ rust-lang/ rust/ issues/ 100013> for more information)
491
+ #[ tokio:: test]
492
+ async fn test_get_auth_config ( ) {
493
+ let named_type = NamedType { } ;
494
+ let _app_secret = named_type. typed_test :: < BasicClientImpl > ( ) . await ;
390
495
}
391
496
}
392
497
}
0 commit comments