22
33use crate :: config:: GatewayConfig ;
44use crate :: multipart:: MultipartManager ;
5+ use blake3:: Hasher ;
56use dashmap:: DashMap ;
67use fula_blockstore:: {
78 FlexibleBlockStore , IpfsPinningBlockStore , IpfsPinningConfig , MemoryBlockStore ,
@@ -10,6 +11,17 @@ use fula_core::BucketManager;
1011use std:: sync:: Arc ;
1112use tracing:: { info, warn} ;
1213
14+ /// Hash a user ID for privacy (Security audit fix A3)
15+ /// This prevents exposing raw user IDs (e.g., email addresses) in stored metadata
16+ pub fn hash_user_id ( user_id : & str ) -> String {
17+ let mut hasher = Hasher :: new ( ) ;
18+ hasher. update ( b"fula:user_id:" ) ; // Domain separation
19+ hasher. update ( user_id. as_bytes ( ) ) ;
20+ let hash = hasher. finalize ( ) ;
21+ // Use first 16 bytes (128 bits) encoded as hex for reasonable uniqueness
22+ hex:: encode ( & hash. as_bytes ( ) [ ..16 ] )
23+ }
24+
1325/// Application state shared across handlers
1426pub struct AppState {
1527 /// Gateway configuration
@@ -95,6 +107,8 @@ impl AppState {
95107pub struct UserSession {
96108 /// User ID (from JWT sub claim)
97109 pub user_id : String ,
110+ /// Hashed user ID for storage (Security audit fix A3)
111+ pub hashed_user_id : String ,
98112 /// Display name
99113 pub display_name : Option < String > ,
100114 /// Scopes
@@ -104,6 +118,18 @@ pub struct UserSession {
104118}
105119
106120impl UserSession {
121+ /// Create a new user session with automatic ID hashing
122+ pub fn new ( user_id : String , display_name : Option < String > , scopes : Vec < String > , expires_at : chrono:: DateTime < chrono:: Utc > ) -> Self {
123+ let hashed_user_id = hash_user_id ( & user_id) ;
124+ Self {
125+ user_id,
126+ hashed_user_id,
127+ display_name,
128+ scopes,
129+ expires_at,
130+ }
131+ }
132+
107133 /// Check if the session has expired
108134 pub fn is_expired ( & self ) -> bool {
109135 chrono:: Utc :: now ( ) > self . expires_at
@@ -130,7 +156,8 @@ impl UserSession {
130156 }
131157
132158 /// Check if user can access a bucket (owner or admin)
159+ /// Security audit fix A3: Uses hashed user ID for comparison
133160 pub fn can_access_bucket ( & self , bucket_owner_id : & str ) -> bool {
134- self . user_id == bucket_owner_id || self . is_admin ( )
161+ self . hashed_user_id == bucket_owner_id || self . is_admin ( )
135162 }
136163}
0 commit comments