@@ -27,35 +27,69 @@ pub enum Filter {
2727#[ derive( Clone , Debug , PartialEq ) ]
2828pub struct User {
2929 pub id : i64 ,
30+ pub access_token : String ,
31+ pub scopes : Vec < OauthScope > ,
3032 pub langs : Option < Vec < String > > ,
3133 pub logged_in : bool ,
3234 pub filter : Filter ,
3335}
36+ #[ derive( Clone , Debug , PartialEq ) ]
37+ pub enum OauthScope {
38+ Read ,
39+ ReadStatuses ,
40+ ReadNotifications ,
41+ ReadList ,
42+ Other ,
43+ }
44+ impl From < & str > for OauthScope {
45+ fn from ( scope : & str ) -> Self {
46+ use OauthScope :: * ;
47+ match scope {
48+ "read" => Read ,
49+ "read:statuses" => ReadStatuses ,
50+ "read:notifications" => ReadNotifications ,
51+ "read:lists" => ReadList ,
52+ _ => Other ,
53+ }
54+ }
55+ }
3456impl User {
3557 /// Create a user from the access token supplied in the header or query paramaters
36- pub fn from_access_token ( token : String , scope : Scope ) -> Result < Self , warp:: reject:: Rejection > {
58+ pub fn from_access_token (
59+ access_token : String ,
60+ scope : Scope ,
61+ ) -> Result < Self , warp:: reject:: Rejection > {
3762 let conn = connect_to_postgres ( ) ;
3863 let result = & conn
3964 . query (
4065 "
41- SELECT oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages
66+ SELECT oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes
4267FROM
4368oauth_access_tokens
4469INNER JOIN users ON
4570oauth_access_tokens.resource_owner_id = users.id
4671WHERE oauth_access_tokens.token = $1
4772AND oauth_access_tokens.revoked_at IS NULL
4873LIMIT 1" ,
49- & [ & token ] ,
74+ & [ & access_token ] ,
5075 )
5176 . expect ( "Hard-coded query will return Some([0 or more rows])" ) ;
5277 if !result. is_empty ( ) {
5378 let only_row = result. get ( 0 ) ;
5479 let id: i64 = only_row. get ( 1 ) ;
80+ let scopes = only_row
81+ . get :: < _ , String > ( 3 )
82+ . split ( ' ' )
83+ . map ( |scope : & str | scope. into ( ) )
84+ . filter ( |scope| scope != & OauthScope :: Other )
85+ . collect ( ) ;
86+ dbg ! ( & scopes) ;
5587 let langs: Option < Vec < String > > = only_row. get ( 2 ) ;
5688 info ! ( "Granting logged-in access" ) ;
5789 Ok ( User {
5890 id,
91+ access_token,
92+ scopes,
5993 langs,
6094 logged_in : true ,
6195 filter : Filter :: None ,
@@ -64,6 +98,8 @@ LIMIT 1",
6498 info ! ( "Granting public access to non-authenticated client" ) ;
6599 Ok ( User {
66100 id : -1 ,
101+ access_token,
102+ scopes : Vec :: new ( ) ,
67103 langs : None ,
68104 logged_in : false ,
69105 filter : Filter :: None ,
@@ -116,6 +152,8 @@ LIMIT 1",
116152 pub fn public ( ) -> Self {
117153 User {
118154 id : -1 ,
155+ access_token : String :: new ( ) ,
156+ scopes : Vec :: new ( ) ,
119157 langs : None ,
120158 logged_in : false ,
121159 filter : Filter :: None ,
@@ -130,16 +168,25 @@ pub enum Scope {
130168}
131169impl Scope {
132170 pub fn get_access_token ( self ) -> warp:: filters:: BoxedFilter < ( String , ) > {
133- let token_from_header = warp:: header:: header :: < String > ( "authorization" )
171+ let token_from_header_http_push = warp:: header:: header :: < String > ( "authorization" )
134172 . map ( |auth : String | auth. split ( ' ' ) . nth ( 1 ) . unwrap_or ( "invalid" ) . to_string ( ) ) ;
173+ let token_from_header_ws =
174+ warp:: header:: header :: < String > ( "Sec-WebSocket-Protocol" ) . map ( |auth : String | auth) ;
135175 let token_from_query = warp:: query ( ) . map ( |q : query:: Auth | q. access_token ) ;
176+
177+ let private_scopes = any_of ! (
178+ token_from_header_http_push,
179+ token_from_header_ws,
180+ token_from_query
181+ ) ;
182+
136183 let public = warp:: any ( ) . map ( || "no access token" . to_string ( ) ) ;
137184
138185 match self {
139186 // if they're trying to access a private scope without an access token, reject the request
140- Scope :: Private => any_of ! ( token_from_query , token_from_header ) . boxed ( ) ,
187+ Scope :: Private => private_scopes . boxed ( ) ,
141188 // if they're trying to access a public scope without an access token, proceed
142- Scope :: Public => any_of ! ( token_from_query , token_from_header , public) . boxed ( ) ,
189+ Scope :: Public => any_of ! ( private_scopes , public) . boxed ( ) ,
143190 }
144191 }
145192}
0 commit comments