@@ -22,16 +22,46 @@ use std::future::{ready, Ready};
2222use actix_web:: {
2323 dev:: { forward_ready, Service , ServiceRequest , ServiceResponse , Transform } ,
2424 error:: { ErrorBadRequest , ErrorUnauthorized } ,
25- Error ,
25+ Error , Route ,
2626} ;
2727use actix_web_httpauth:: extractors:: basic:: BasicAuth ;
2828use futures_util:: future:: LocalBoxFuture ;
2929
3030use crate :: { option:: CONFIG , rbac:: role:: Action , rbac:: Users } ;
3131
32+ pub trait RouteExt {
33+ fn authorize ( self , action : Action ) -> Self ;
34+ fn authorize_for_stream ( self , action : Action ) -> Self ;
35+ fn authorize_for_user ( self , action : Action ) -> Self ;
36+ }
37+
38+ impl RouteExt for Route {
39+ fn authorize ( self , action : Action ) -> Self {
40+ self . wrap ( Auth {
41+ action,
42+ method : auth_no_context,
43+ } )
44+ }
45+
46+ fn authorize_for_stream ( self , action : Action ) -> Self {
47+ self . wrap ( Auth {
48+ action,
49+ method : auth_stream_context,
50+ } )
51+ }
52+
53+ fn authorize_for_user ( self , action : Action ) -> Self {
54+ self . wrap ( Auth {
55+ action,
56+ method : auth_user_context,
57+ } )
58+ }
59+ }
60+
61+ // Authentication Layer with no context
3262pub struct Auth {
3363 pub action : Action ,
34- pub stream : bool ,
64+ pub method : fn ( & mut ServiceRequest , Action ) -> Result < bool , Error > ,
3565}
3666
3767impl < S , B > Transform < S , ServiceRequest > for Auth
@@ -49,15 +79,15 @@ where
4979 fn new_transform ( & self , service : S ) -> Self :: Future {
5080 ready ( Ok ( AuthMiddleware {
5181 action : self . action ,
52- match_stream : self . stream ,
5382 service,
83+ auth_method : self . method ,
5484 } ) )
5585 }
5686}
5787
5888pub struct AuthMiddleware < S > {
5989 action : Action ,
60- match_stream : bool ,
90+ auth_method : fn ( & mut ServiceRequest , Action ) -> Result < bool , Error > ,
6191 service : S ,
6292}
6393
@@ -74,38 +104,46 @@ where
74104 forward_ready ! ( service) ;
75105
76106 fn call ( & self , mut req : ServiceRequest ) -> Self :: Future {
77- // Extract username and password from the request using basic auth extractor.
78- let creds = req. extract :: < BasicAuth > ( ) . into_inner ( ) ;
79- let creds = creds. map_err ( Into :: into) . map ( |creds| {
80- let username = creds. user_id ( ) . trim ( ) . to_owned ( ) ;
81- // password is not mandatory by basic auth standard.
82- // If not provided then treat as empty string
83- let password = creds. password ( ) . unwrap_or ( "" ) . trim ( ) . to_owned ( ) ;
84- ( username, password)
85- } ) ;
86-
87- let stream = if self . match_stream {
88- req. match_info ( ) . get ( "logstream" )
89- } else {
90- None
91- } ;
92-
93- let auth_result: Result < bool , Error > = creds. map ( |( username, password) | {
94- Users . authenticate ( username, password, self . action , stream)
95- } ) ;
96-
107+ let auth_result: Result < bool , Error > = ( self . auth_method ) ( & mut req, self . action ) ;
97108 let fut = self . service . call ( req) ;
98-
99109 Box :: pin ( async move {
100110 if !auth_result? {
101111 return Err ( ErrorUnauthorized ( "Not authorized" ) ) ;
102112 }
103-
104113 fut. await
105114 } )
106115 }
107116}
108117
118+ pub fn auth_no_context ( req : & mut ServiceRequest , action : Action ) -> Result < bool , Error > {
119+ let creds = extract_basic_auth ( req) ;
120+ creds. map ( |( username, password) | Users . authenticate ( username, password, action, None , None ) )
121+ }
122+
123+ pub fn auth_stream_context ( req : & mut ServiceRequest , action : Action ) -> Result < bool , Error > {
124+ let creds = extract_basic_auth ( req) ;
125+ let stream = req. match_info ( ) . get ( "logstream" ) ;
126+ creds. map ( |( username, password) | Users . authenticate ( username, password, action, stream, None ) )
127+ }
128+
129+ pub fn auth_user_context ( req : & mut ServiceRequest , action : Action ) -> Result < bool , Error > {
130+ let creds = extract_basic_auth ( req) ;
131+ let user = req. match_info ( ) . get ( "username" ) ;
132+ creds. map ( |( username, password) | Users . authenticate ( username, password, action, None , user) )
133+ }
134+
135+ fn extract_basic_auth ( req : & mut ServiceRequest ) -> Result < ( String , String ) , Error > {
136+ // Extract username and password from the request using basic auth extractor.
137+ let creds = req. extract :: < BasicAuth > ( ) . into_inner ( ) ;
138+ creds. map_err ( Into :: into) . map ( |creds| {
139+ let username = creds. user_id ( ) . trim ( ) . to_owned ( ) ;
140+ // password is not mandatory by basic auth standard.
141+ // If not provided then treat as empty string
142+ let password = creds. password ( ) . unwrap_or ( "" ) . trim ( ) . to_owned ( ) ;
143+ ( username, password)
144+ } )
145+ }
146+
109147// The credentials set in the env vars (P_USERNAME & P_PASSWORD) are treated
110148// as root credentials. Any other user is not allowed to modify or delete
111149// the root user. Deny request if username is same as username
0 commit comments