386 lines
14 KiB
C#
386 lines
14 KiB
C#
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<int>();
|
|
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<int> GetCheckedPermissions()
|
|
{
|
|
var list = new List<int>();
|
|
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);
|
|
}
|
|
}
|
|
}
|