@@ -9,7 +9,8 @@ use std::collections::HashMap;
99use std:: error:: Error ;
1010use std:: fs:: OpenOptions ;
1111use std:: io:: { BufReader , BufWriter , ErrorKind } ;
12- use std:: { fmt, io} ;
12+ use std:: { fmt, fs, io} ;
13+ use std:: time:: SystemTime ;
1314use uuid:: Uuid ;
1415
1516#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -60,6 +61,16 @@ impl UserDB {
6061 Uuid :: now_v7 ( ) . to_string ( )
6162 }
6263
64+ /// Clears the token for a user and updates the token_to_uid map
65+ pub fn clear_user_token ( & mut self , uid : isize ) {
66+ if let Some ( user) = self . users . get_mut ( & uid) {
67+ if let Some ( token) = & user. token {
68+ self . token_to_uid . remove ( token) ;
69+ }
70+ user. token = None ;
71+ }
72+ }
73+
6374 /// Creates a new `UserDB` instance with the given file path and writes the empty database to the file.
6475 pub fn new ( file_path : & str ) -> UserDB {
6576 info ! ( "Creating a new user database with file path: {}" , file_path) ;
@@ -196,31 +207,63 @@ impl UserDB {
196207 pub fn logout ( & mut self , uid : isize ) -> Result < ( ) , Box < dyn Error > > {
197208 if let Some ( user) = self . users . get_mut ( & uid) {
198209 ContainerManager :: logout_user ( user, & mut self . traefik_instances ) ?;
199- if let Some ( token) = & user. token {
200- self . token_to_uid . remove ( token) ; // Remove the token from the map
201- }
202- user. token = None ;
203- info ! ( "User '{}' logged out successfully" , user. username) ;
210+ let username = user. username . clone ( ) ;
211+ self . clear_user_token ( uid) ; // Clear the user's token
212+ info ! ( "User '{}' logged out successfully" , username) ;
204213 } else {
205214 error ! ( "User with UID {} not found for logout" , uid) ;
206215 return Err ( Box :: new ( LoginError :: UserNotFound ) ) ;
207216 }
208217 Ok ( ( ) )
209218 }
210-
211-
219+
212220 /// Checks and stops containers that have been idle for more than 1200 seconds.
213221 pub fn check_expiration ( & mut self ) {
214- ContainerManager :: check_expiration ( self . users . values_mut ( ) , & mut self . traefik_instances ) ;
222+ let mut user_clone = self . users . clone ( ) ;
223+ for user in user_clone. values_mut ( ) {
224+ let heartbeat_path = format ! (
225+ "{}/{}.data/home/.local/share/code-server/heartbeat" ,
226+ * crate :: storage:: DATADIR , user. uid
227+ ) ;
228+
229+ match fs:: metadata ( & heartbeat_path)
230+ . and_then ( |metadata| metadata. modified ( ) )
231+ . and_then ( |modified_time| {
232+ SystemTime :: now ( )
233+ . duration_since ( modified_time)
234+ . map_err ( |e| io:: Error :: new ( ErrorKind :: Other , e) )
235+ } ) {
236+ Ok ( duration) if duration. as_secs ( ) >= 1200 => {
237+ // If the user has been idle for more than 1200 seconds
238+ if let Err ( e) = self . logout ( user. uid ) {
239+ error ! ( "Failed to log out user '{}': {}" , user. username, e) ;
240+ } else {
241+ info ! (
242+ "User '{}' has been idle for {} seconds and logged out." ,
243+ user. username, duration. as_secs( )
244+ ) ;
245+ }
246+ }
247+ Ok ( duration) => {
248+ info ! (
249+ "User '{}' has been idle for {} seconds." ,
250+ user. username, duration. as_secs( )
251+ ) ;
252+ }
253+ Err ( e) => {
254+ error ! ( "Failed to check user status '{}': {}" , user. username, e) ;
255+ }
256+ }
257+ }
215258 }
216259
217260 /// Logs out all users by stopping their containers and clearing their tokens.
218261 pub fn logout_all_users ( & mut self ) -> Result < ( ) , Box < dyn Error > > {
219262 ContainerManager :: logout_all_users ( self . users . values_mut ( ) , & mut self . traefik_instances ) ?;
220263
221- // Clear tokens for all users
222- for user in self . users . values_mut ( ) {
223- user . token = None ;
264+ // Clear tokens for all users using the new method
265+ for uid in self . users . keys ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) {
266+ self . clear_user_token ( uid ) ;
224267 }
225268
226269 Ok ( ( ) )
0 commit comments