Skip to content

Commit 3fe5f20

Browse files
committed
fix logout issue
1 parent 7797275 commit 3fe5f20

2 files changed

Lines changed: 58 additions & 57 deletions

File tree

src/container.rs

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{
88
};
99

1010
use crate::{
11-
storage::{DATADIR, DOCKER_IMAGE},
11+
storage::DOCKER_IMAGE,
1212
traefik::{self, Instance},
1313
user::User,
1414
};
@@ -168,47 +168,6 @@ impl ContainerManager {
168168
}
169169
}
170170

171-
/// Check and stop expired containers
172-
pub fn check_expiration<'a>(
173-
users: impl Iterator<Item = &'a mut User>,
174-
traefik_instances: &mut traefik::Instances,
175-
) {
176-
for user in users {
177-
let heartbeat_path = format!(
178-
"{}/{}.data/home/.local/share/code-server/heartbeat",
179-
*DATADIR, user.uid
180-
);
181-
182-
match fs::metadata(&heartbeat_path)
183-
.and_then(|metadata| metadata.modified())
184-
.and_then(|modified_time| {
185-
SystemTime::now()
186-
.duration_since(modified_time)
187-
.map_err(|e| io::Error::new(ErrorKind::Other, e))
188-
}) {
189-
Ok(duration) if duration.as_secs() >= 1200 => {
190-
if let Err(e) = Self::logout_user(user, traefik_instances) {
191-
error!("Failed to log out user '{}': {}", user.username, e);
192-
} else {
193-
info!(
194-
"User '{}' has been idled for {} seconds and logged out.",
195-
user.username, duration.as_secs()
196-
);
197-
}
198-
}
199-
Ok(duration) => {
200-
info!(
201-
"User '{}' has been idled for {} seconds.",
202-
user.username, duration.as_secs()
203-
);
204-
}
205-
Err(e) => {
206-
error!("Failed to check user status '{}': {}", user.username, e);
207-
}
208-
}
209-
}
210-
}
211-
212171
/// Log out a user
213172
pub fn logout_user(
214173
user: &mut User,
@@ -221,9 +180,8 @@ impl ContainerManager {
221180
Self::stop_container(&container_id, traefik_instances)?;
222181
}
223182

224-
// Clear the user's token
225-
user.token = None;
226-
info!("Cleared token for user: {}", user.username);
183+
// No longer clear the user's token here
184+
info!("Container stopped for user: {}", user.username);
227185

228186
Ok(())
229187
}

src/user.rs

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use std::collections::HashMap;
99
use std::error::Error;
1010
use std::fs::OpenOptions;
1111
use std::io::{BufReader, BufWriter, ErrorKind};
12-
use std::{fmt, io};
12+
use std::{fmt, fs, io};
13+
use std::time::SystemTime;
1314
use 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

Comments
 (0)