using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace UserPermissionTest_CS_WinForms { public partial class UserSettings : Form { private string? _editingUsername = null; // null means we are adding a new user, otherwise contains the original username of the user being edited. private bool _isPopulatingFields = false; public UserSettings() { InitializeComponent(); } private void UserSettings_Load(object sender, EventArgs e) { RefreshUserList(); // Register to updates to keep UI synchronized in real-time SessionManager.UsersUpdated += SessionManager_UsersUpdated; if (lstUsers.Items.Count > 0) { lstUsers.SelectedIndex = 0; } else { ClearDetailsForm(); } } private void SessionManager_UsersUpdated() { // Safeguard for cross-thread calls, though in WinForms it's usually on the UI thread if (this.InvokeRequired) { this.Invoke(new Action(RefreshUserList)); } else { RefreshUserList(); } } private void RefreshUserList() { _isPopulatingFields = true; string? currentSelection = lstUsers.SelectedItem?.ToString(); lstUsers.Items.Clear(); foreach (var user in SessionManager.Users) { lstUsers.Items.Add(user.Username); } // Restore selection if possible if (currentSelection != null && lstUsers.Items.Contains(currentSelection)) { lstUsers.SelectedItem = currentSelection; } else if (lstUsers.Items.Count > 0) { lstUsers.SelectedIndex = 0; } else { ClearDetailsForm(); } _isPopulatingFields = false; RefreshPermissionList(); } private void RefreshPermissionList() { // Save currently checked permission IDs var checkedPermIds = new HashSet(); for (int i = 0; i < chkPermissions.Items.Count; i++) { if (chkPermissions.GetItemChecked(i)) { var permission = chkPermissions.Items[i] as Permission; if (permission != null) { checkedPermIds.Add(permission.Id); } } } chkPermissions.Items.Clear(); foreach (var permission in SessionManager.AvailablePermissions) { chkPermissions.Items.Add(permission); } // If we are editing a user, check their specific permissions if (_editingUsername != null) { var user = SessionManager.Users.FirstOrDefault(u => u.Username.Equals(_editingUsername, StringComparison.OrdinalIgnoreCase)); if (user != null) { for (int i = 0; i < chkPermissions.Items.Count; i++) { var permission = chkPermissions.Items[i] as Permission; if (permission != null && user.Permissions.Contains(permission.Id)) { chkPermissions.SetItemChecked(i, true); } } } } else { // Otherwise, restore the checks that the administrator was in the middle of selecting for (int i = 0; i < chkPermissions.Items.Count; i++) { var permission = chkPermissions.Items[i] as Permission; if (permission != null && checkedPermIds.Contains(permission.Id)) { chkPermissions.SetItemChecked(i, true); } } } } private void lstUsers_SelectedIndexChanged(object sender, EventArgs e) { if (_isPopulatingFields) return; string? selectedUsername = lstUsers.SelectedItem?.ToString(); if (selectedUsername != null) { var user = SessionManager.Users.FirstOrDefault(u => u.Username.Equals(selectedUsername, StringComparison.OrdinalIgnoreCase)); if (user != null) { PopulateUserDetails(user); } } else { ClearDetailsForm(); } } private void PopulateUserDetails(User user) { _isPopulatingFields = true; _editingUsername = user.Username; txtUsername.Text = user.Username; txtFullName.Text = user.FullName; // Mask the actual password on display with a special visual placeholder txtPassword.Text = "●●●●●●●●"; txtPassword.PasswordChar = '•'; btnTogglePassword.Text = "👁"; // Update permissions CheckedListBox for (int i = 0; i < chkPermissions.Items.Count; i++) { var permission = chkPermissions.Items[i] as Permission; bool hasPermission = permission != null && user.Permissions.Contains(permission.Id); chkPermissions.SetItemChecked(i, hasPermission); } lblDetailsHeader.Text = $"User Profile: {user.Username}"; btnDeleteUser.Enabled = true; _isPopulatingFields = false; } private void ClearDetailsForm() { _isPopulatingFields = true; _editingUsername = null; txtUsername.Text = string.Empty; txtFullName.Text = string.Empty; txtPassword.Text = string.Empty; txtPassword.PasswordChar = '•'; btnTogglePassword.Text = "👁"; for (int i = 0; i < chkPermissions.Items.Count; i++) { chkPermissions.SetItemChecked(i, false); } lblDetailsHeader.Text = "New User Profile Setup"; btnDeleteUser.Enabled = false; _isPopulatingFields = false; } private void btnAddUser_Click(object sender, EventArgs e) { lstUsers.ClearSelected(); ClearDetailsForm(); txtUsername.Focus(); } private void btnDeleteUser_Click(object sender, EventArgs e) { if (_editingUsername == null) return; var result = MessageBox.Show( $"Are you sure you want to delete the user '{_editingUsername}'?", "Confirm Deletion", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (result == DialogResult.Yes) { SessionManager.DeleteUser(_editingUsername); } } private void btnSaveUser_Click(object sender, EventArgs e) { string username = txtUsername.Text.Trim(); string fullName = txtFullName.Text.Trim(); string password = txtPassword.Text; if (string.IsNullOrEmpty(username)) { MessageBox.Show("Username cannot be empty.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); txtUsername.Focus(); return; } if (string.IsNullOrEmpty(fullName)) { MessageBox.Show("Full Name cannot be empty.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); txtFullName.Focus(); return; } if (string.IsNullOrEmpty(password)) { MessageBox.Show("Password cannot be empty.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); txtPassword.Focus(); return; } // Check duplicate username bool isNewUser = _editingUsername == null; bool usernameExists = SessionManager.Users.Any(u => u.Username.Equals(username, StringComparison.OrdinalIgnoreCase)); // Determine final password hash to save string finalPasswordHash; if (isNewUser) { if (usernameExists) { MessageBox.Show($"A user with username '{username}' already exists.", "Duplicate Username", MessageBoxButtons.OK, MessageBoxIcon.Error); txtUsername.Focus(); return; } if (password == "●●●●●●●●") { MessageBox.Show("Please enter a valid password for the new user.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); txtPassword.Focus(); return; } finalPasswordHash = PasswordHasher.HashPassword(password); var newUser = new User { Username = username, FullName = fullName, Password = finalPasswordHash, Permissions = GetCheckedPermissions() }; SessionManager.AddUser(newUser); MessageBox.Show($"User '{username}' created successfully.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); // Select the newly created user lstUsers.SelectedItem = username; } else { // Editing existing user if (!username.Equals(_editingUsername, StringComparison.OrdinalIgnoreCase) && usernameExists) { MessageBox.Show($"A user with username '{username}' already exists.", "Duplicate Username", MessageBoxButtons.OK, MessageBoxIcon.Error); txtUsername.Focus(); return; } var existingUser = SessionManager.Users.FirstOrDefault(u => u.Username.Equals(_editingUsername, StringComparison.OrdinalIgnoreCase)); if (password == "●●●●●●●●" || string.IsNullOrEmpty(password)) { // Keep existing hashed password finalPasswordHash = existingUser != null ? existingUser.Password : PasswordHasher.HashPassword("admin"); } else { // Hash new password finalPasswordHash = PasswordHasher.HashPassword(password); } var updatedUser = new User { Username = username, FullName = fullName, Password = finalPasswordHash, Permissions = GetCheckedPermissions() }; string originalName = _editingUsername!; SessionManager.UpdateUser(originalName, updatedUser); MessageBox.Show($"User details for '{username}' updated successfully.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); // Keep the selection updated lstUsers.SelectedItem = username; } } private void btnTogglePassword_Click(object sender, EventArgs e) { if (txtPassword.PasswordChar == '•') { txtPassword.PasswordChar = '\0'; // Show password btnTogglePassword.Text = "🙈"; } else { txtPassword.PasswordChar = '•'; // Mask password btnTogglePassword.Text = "👁"; } } private List GetCheckedPermissions() { var list = new List(); for (int i = 0; i < chkPermissions.Items.Count; i++) { if (chkPermissions.GetItemChecked(i)) { var permission = chkPermissions.Items[i] as Permission; if (permission != null) { list.Add(permission.Id); } } } return list; } private void btnAddNewPermission_Click(object sender, EventArgs e) { string newPerm = txtNewPermission.Text.Trim(); if (string.IsNullOrEmpty(newPerm)) { MessageBox.Show("Please enter a permission name.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); txtNewPermission.Focus(); return; } if (SessionManager.AvailablePermissions.Any(p => p.Name.Equals(newPerm, StringComparison.OrdinalIgnoreCase))) { MessageBox.Show($"Permission '{newPerm}' already exists in the system.", "Duplicate Permission", MessageBoxButtons.OK, MessageBoxIcon.Warning); txtNewPermission.Focus(); return; } SessionManager.AddPermission(newPerm); txtNewPermission.Clear(); RefreshPermissionList(); MessageBox.Show($"New permission '{newPerm}' registered. You can now assign it to users.", "Permission Registered", MessageBoxButtons.OK, MessageBoxIcon.Information); } protected override void OnFormClosing(FormClosingEventArgs e) { // Unsubscribe to prevent memory leaks SessionManager.UsersUpdated -= SessionManager_UsersUpdated; base.OnFormClosing(e); } } }