@@ -104,11 +104,28 @@ type LoadFuture<DocCtx> =
104104type SaveFuture = Pin < Box < dyn Future < Output = Result < ( ) , String > > + Send + ' static > > ;
105105type LoadFn < DocCtx > = Arc < dyn Fn ( LoadDocArgs ) -> LoadFuture < DocCtx > + Send + Sync > ;
106106type SaveFn < DocCtx > = Arc < dyn Fn ( SaveDocArgs < DocCtx > ) -> SaveFuture + Send + Sync > ;
107+
108+ /// Arguments provided to `authenticate`.
109+ pub struct AuthArgs {
110+ pub room : String ,
111+ pub crdt : CrdtType ,
112+ pub auth : Vec < u8 > ,
113+ pub conn_id : u64 ,
114+ }
115+
107116type AuthFuture =
108117 Pin < Box < dyn Future < Output = Result < Option < Permission > , String > > + Send + ' static > > ;
109- type AuthFn = Arc < dyn Fn ( String , CrdtType , Vec < u8 > ) -> AuthFuture + Send + Sync > ;
118+ type AuthFn = Arc < dyn Fn ( AuthArgs ) -> AuthFuture + Send + Sync > ;
119+
120+ /// Arguments provided to `handshake_auth`.
121+ pub struct HandshakeAuthArgs < ' a > {
122+ pub workspace : & ' a str ,
123+ pub token : Option < & ' a str > ,
124+ pub request : & ' a tungstenite:: handshake:: server:: Request ,
125+ pub conn_id : u64 ,
126+ }
110127
111- type HandshakeAuthFn = dyn Fn ( & str , Option < & str > , & tungstenite :: handshake :: server :: Request ) -> bool + Send + Sync ;
128+ type HandshakeAuthFn = dyn Fn ( HandshakeAuthArgs ) -> bool + Send + Sync ;
112129
113130#[ derive( Clone ) ]
114131pub struct ServerConfig < DocCtx = ( ) > {
@@ -123,6 +140,7 @@ pub struct ServerConfig<DocCtx = ()> {
123140 /// - `workspace_id`: extracted from request path `/{workspace}` (empty if missing)
124141 /// - `token`: `token` query parameter if present
125142 /// - `request`: the full HTTP request (headers, uri, etc)
143+ /// - `conn_id`: the connection id
126144 ///
127145 /// Return true to accept, false to reject with 401.
128146 pub handshake_auth : Option < Arc < HandshakeAuthFn > > ,
@@ -885,12 +903,17 @@ async fn handle_conn<DocCtx>(
885903where
886904 DocCtx : Clone + Send + Sync + ' static ,
887905{
906+
907+ // Generate a connection id
908+ let conn_id = NEXT_ID . fetch_add ( 1 , Ordering :: Relaxed ) ;
909+
888910 // Capture config outside of non-async closure
889911 let handshake_auth = registry. config . handshake_auth . clone ( ) ;
890912 let workspace_holder: Arc < std:: sync:: Mutex < Option < String > > > =
891913 Arc :: new ( std:: sync:: Mutex :: new ( None ) ) ;
892914 let workspace_holder_c = workspace_holder. clone ( ) ;
893915
916+
894917 let ws = accept_hdr_async (
895918 stream,
896919 move |req : & tungstenite:: handshake:: server:: Request ,
@@ -926,7 +949,12 @@ where
926949 None
927950 } ) ;
928951
929- let allowed = ( check) ( workspace_id, token, req) ;
952+ let allowed = ( check) ( HandshakeAuthArgs {
953+ workspace : workspace_id,
954+ token,
955+ request : req,
956+ conn_id,
957+ } ) ;
930958 if !allowed {
931959 warn ! ( workspace=%workspace_id, token=?token, "handshake auth denied" ) ;
932960 // Build a 401 Unauthorized response
@@ -972,7 +1000,6 @@ where
9721000 }
9731001 } ) ;
9741002
975- let conn_id = NEXT_ID . fetch_add ( 1 , Ordering :: Relaxed ) ;
9761003 let mut joined_rooms: HashSet < RoomKey > = HashSet :: new ( ) ;
9771004
9781005 while let Some ( msg) = stream. next ( ) . await {
@@ -1002,7 +1029,14 @@ where
10021029 let mut permission = h. config . default_permission ;
10031030 if let Some ( auth_fn) = & h. config . authenticate {
10041031 let room_str = room. room . clone ( ) ;
1005- match ( auth_fn) ( room_str, room. crdt , auth. clone ( ) ) . await {
1032+ match ( auth_fn) ( AuthArgs {
1033+ room : room_str,
1034+ crdt : room. crdt ,
1035+ auth : auth. clone ( ) ,
1036+ conn_id,
1037+ } )
1038+ . await
1039+ {
10061040 Ok ( Some ( p) ) => {
10071041 permission = p;
10081042 }
0 commit comments