using Guna.UI2.WinForms; using Npgsql; using System; using System.Data; using System.Threading.Tasks; using System.Windows.Forms; namespace DeanOfficeApp { public partial class UserManagementForm : Form { private Guna2DataGridView dgvUsers; private Guna2TextBox txtUsername, txtPassword, txtFullName; private Guna2ComboBox cmbRole; private Guna2Button btnAdd, btnUpdate, btnDelete, btnRefresh; private Guna2HtmlLabel lblUsername, lblPassword, lblFullName, lblRole; private readonly string _connString = "Host=245e1-rw.db.pub.dbaas.postgrespro.ru;Port=5432;Database=dbpractice;Username=mardasov_mv;Password=A4%2x$$2Ynr"; public UserManagementForm() { InitializeComponent(); this.Load += async (s, e) => await LoadUsersAsync(); } // Асинхронная загрузка списка пользователей private async Task LoadUsersAsync() { try { Cursor = Cursors.WaitCursor; string sql = "SELECT user_id, username, role, full_name FROM appuser ORDER BY user_id"; using (var conn = new NpgsqlConnection(_connString)) { await conn.OpenAsync(); using (var cmd = new NpgsqlCommand(sql, conn)) { var dt = new DataTable(); dt.Load(await cmd.ExecuteReaderAsync()); dgvUsers.DataSource = dt; if (dgvUsers.Columns.Contains("user_id")) dgvUsers.Columns["user_id"].Visible = false; } } } catch (Exception ex) { MessageBox.Show($"Ошибка загрузки пользователей: {ex.Message}"); } finally { Cursor = Cursors.Default; } } // Хеширование пароля через BCrypt private string HashPassword(string password) => BCrypt.Net.BCrypt.HashPassword(password); // Добавление нового пользователя private async void btnAdd_Click(object sender, EventArgs e) { string username = txtUsername.Text.Trim(); string password = txtPassword.Text.Trim(); string fullName = txtFullName.Text.Trim(); string role = cmbRole.SelectedItem?.ToString(); if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(role)) { MessageBox.Show("Заполните логин, пароль и роль."); return; } string hash = HashPassword(password); string sql = "INSERT INTO appuser (username, password_hash, role, full_name) VALUES (@u, @p, @r, @f)"; try { Cursor = Cursors.WaitCursor; using (var conn = new NpgsqlConnection(_connString)) { await conn.OpenAsync(); using (var cmd = new NpgsqlCommand(sql, conn)) { cmd.Parameters.AddWithValue("@u", username); cmd.Parameters.AddWithValue("@p", hash); cmd.Parameters.AddWithValue("@r", role); cmd.Parameters.AddWithValue("@f", fullName); await cmd.ExecuteNonQueryAsync(); } } await LoadUsersAsync(); ClearFields(); MessageBox.Show("Пользователь добавлен."); } catch (Exception ex) { MessageBox.Show($"Ошибка: {ex.Message}"); } finally { Cursor = Cursors.Default; } } // Обновление данных пользователя private async void btnUpdate_Click(object sender, EventArgs e) { if (dgvUsers.CurrentRow == null) { MessageBox.Show("Выберите пользователя для обновления."); return; } int userId = (int)dgvUsers.CurrentRow.Cells["user_id"].Value; string username = txtUsername.Text.Trim(); string password = txtPassword.Text.Trim(); string fullName = txtFullName.Text.Trim(); string role = cmbRole.SelectedItem?.ToString(); if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(role)) { MessageBox.Show("Заполните логин и роль."); return; } try { Cursor = Cursors.WaitCursor; using (var conn = new NpgsqlConnection(_connString)) { await conn.OpenAsync(); NpgsqlCommand cmd; if (!string.IsNullOrEmpty(password)) { string hash = HashPassword(password); string sql = "UPDATE appuser SET username=@u, password_hash=@p, role=@r, full_name=@f WHERE user_id=@id"; cmd = new NpgsqlCommand(sql, conn); cmd.Parameters.AddWithValue("@p", hash); } else { string sql = "UPDATE appuser SET username=@u, role=@r, full_name=@f WHERE user_id=@id"; cmd = new NpgsqlCommand(sql, conn); } cmd.Parameters.AddWithValue("@u", username); cmd.Parameters.AddWithValue("@r", role); cmd.Parameters.AddWithValue("@f", fullName); cmd.Parameters.AddWithValue("@id", userId); await cmd.ExecuteNonQueryAsync(); } await LoadUsersAsync(); ClearFields(); MessageBox.Show("Пользователь обновлён."); } catch (Exception ex) { MessageBox.Show($"Ошибка: {ex.Message}"); } finally { Cursor = Cursors.Default; } } // Удаление пользователя private async void btnDelete_Click(object sender, EventArgs e) { if (dgvUsers.CurrentRow == null) { MessageBox.Show("Выберите пользователя для удаления."); return; } int userId = (int)dgvUsers.CurrentRow.Cells["user_id"].Value; if (MessageBox.Show("Удалить пользователя?", "Подтверждение", MessageBoxButtons.YesNo) != DialogResult.Yes) return; try { Cursor = Cursors.WaitCursor; using (var conn = new NpgsqlConnection(_connString)) { await conn.OpenAsync(); var cmd = new NpgsqlCommand("DELETE FROM appuser WHERE user_id=@id", conn); cmd.Parameters.AddWithValue("@id", userId); await cmd.ExecuteNonQueryAsync(); } await LoadUsersAsync(); ClearFields(); MessageBox.Show("Пользователь удалён."); } catch (Exception ex) { MessageBox.Show($"Ошибка: {ex.Message}"); } finally { Cursor = Cursors.Default; } } // Обновить список пользователей private async void btnRefresh_Click(object sender, EventArgs e) { await LoadUsersAsync(); ClearFields(); } // Заполнение полей при выборе строки в таблице private void dgvUsers_SelectionChanged(object sender, EventArgs e) { if (dgvUsers.CurrentRow != null) { txtUsername.Text = dgvUsers.CurrentRow.Cells["username"].Value.ToString(); txtFullName.Text = dgvUsers.CurrentRow.Cells["full_name"].Value?.ToString() ?? ""; string role = dgvUsers.CurrentRow.Cells["role"].Value.ToString(); cmbRole.SelectedItem = role; txtPassword.Text = ""; // пароль не отображаем } } private void ClearFields() { txtUsername.Clear(); txtPassword.Clear(); txtFullName.Clear(); cmbRole.SelectedIndex = -1; } // Пустой обработчик (можно удалить, но оставлен для совместимости) private void UserManagementForm_Load(object sender, EventArgs e) { } // ==================== ДИЗАЙНЕР ==================== // Ниже расположен полный код InitializeComponent, сгенерированный конструктором. // Он должен быть идентичен вашему существующему, но я привожу его для полноты. private void InitializeComponent() { System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle(); this.dgvUsers = new Guna.UI2.WinForms.Guna2DataGridView(); this.txtUsername = new Guna.UI2.WinForms.Guna2TextBox(); this.txtPassword = new Guna.UI2.WinForms.Guna2TextBox(); this.txtFullName = new Guna.UI2.WinForms.Guna2TextBox(); this.cmbRole = new Guna.UI2.WinForms.Guna2ComboBox(); this.btnAdd = new Guna.UI2.WinForms.Guna2Button(); this.btnUpdate = new Guna.UI2.WinForms.Guna2Button(); this.btnDelete = new Guna.UI2.WinForms.Guna2Button(); this.btnRefresh = new Guna.UI2.WinForms.Guna2Button(); this.lblUsername = new Guna.UI2.WinForms.Guna2HtmlLabel(); this.lblPassword = new Guna.UI2.WinForms.Guna2HtmlLabel(); this.lblFullName = new Guna.UI2.WinForms.Guna2HtmlLabel(); this.lblRole = new Guna.UI2.WinForms.Guna2HtmlLabel(); ((System.ComponentModel.ISupportInitialize)(this.dgvUsers)).BeginInit(); this.SuspendLayout(); // // dgvUsers // this.dgvUsers.AllowUserToAddRows = false; this.dgvUsers.AllowUserToDeleteRows = false; dataGridViewCellStyle1.BackColor = System.Drawing.Color.White; this.dgvUsers.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1; dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; dataGridViewCellStyle2.BackColor = System.Drawing.Color.FromArgb(100, 88, 255); dataGridViewCellStyle2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 204); dataGridViewCellStyle2.ForeColor = System.Drawing.Color.White; dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight; dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText; dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.True; this.dgvUsers.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle2; this.dgvUsers.ColumnHeadersHeight = 40; dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; dataGridViewCellStyle3.BackColor = System.Drawing.Color.White; dataGridViewCellStyle3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 204); dataGridViewCellStyle3.ForeColor = System.Drawing.Color.FromArgb(71, 69, 94); dataGridViewCellStyle3.SelectionBackColor = System.Drawing.Color.FromArgb(231, 229, 255); dataGridViewCellStyle3.SelectionForeColor = System.Drawing.Color.FromArgb(71, 69, 94); dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.False; this.dgvUsers.DefaultCellStyle = dataGridViewCellStyle3; this.dgvUsers.GridColor = System.Drawing.Color.FromArgb(230, 230, 230); this.dgvUsers.Location = new System.Drawing.Point(20, 160); this.dgvUsers.Name = "dgvUsers"; this.dgvUsers.ReadOnly = true; this.dgvUsers.RowHeadersVisible = false; this.dgvUsers.RowTemplate.Height = 30; this.dgvUsers.Size = new System.Drawing.Size(760, 320); this.dgvUsers.TabIndex = 0; this.dgvUsers.SelectionChanged += new System.EventHandler(this.dgvUsers_SelectionChanged); // // txtUsername // this.txtUsername.Cursor = System.Windows.Forms.Cursors.IBeam; this.txtUsername.DefaultText = ""; this.txtUsername.Font = new System.Drawing.Font("Segoe UI", 9F); this.txtUsername.Location = new System.Drawing.Point(150, 20); this.txtUsername.Name = "txtUsername"; this.txtUsername.PlaceholderText = "Логин"; this.txtUsername.Size = new System.Drawing.Size(200, 36); this.txtUsername.TabIndex = 1; // // txtPassword // this.txtPassword.Cursor = System.Windows.Forms.Cursors.IBeam; this.txtPassword.DefaultText = ""; this.txtPassword.Font = new System.Drawing.Font("Segoe UI", 9F); this.txtPassword.Location = new System.Drawing.Point(150, 70); this.txtPassword.Name = "txtPassword"; this.txtPassword.PlaceholderText = "Пароль (оставьте пустым, чтобы не менять)"; this.txtPassword.Size = new System.Drawing.Size(200, 36); this.txtPassword.TabIndex = 2; // // txtFullName // this.txtFullName.Cursor = System.Windows.Forms.Cursors.IBeam; this.txtFullName.DefaultText = ""; this.txtFullName.Font = new System.Drawing.Font("Segoe UI", 9F); this.txtFullName.Location = new System.Drawing.Point(150, 120); this.txtFullName.Name = "txtFullName"; this.txtFullName.PlaceholderText = "Полное имя"; this.txtFullName.Size = new System.Drawing.Size(200, 36); this.txtFullName.TabIndex = 3; // // cmbRole // this.cmbRole.BackColor = System.Drawing.Color.Transparent; this.cmbRole.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; this.cmbRole.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbRole.Font = new System.Drawing.Font("Segoe UI", 10F); this.cmbRole.ForeColor = System.Drawing.Color.FromArgb(68, 88, 112); this.cmbRole.ItemHeight = 30; this.cmbRole.Items.AddRange(new object[] { "admin", "manager", "teacher", "student" }); this.cmbRole.Location = new System.Drawing.Point(150, 170); this.cmbRole.Name = "cmbRole"; this.cmbRole.Size = new System.Drawing.Size(200, 36); this.cmbRole.TabIndex = 4; // // btnAdd // this.btnAdd.BorderRadius = 8; this.btnAdd.FillColor = System.Drawing.Color.FromArgb(40, 167, 69); this.btnAdd.Font = new System.Drawing.Font("Segoe UI", 9F); this.btnAdd.ForeColor = System.Drawing.Color.White; this.btnAdd.Location = new System.Drawing.Point(400, 20); this.btnAdd.Name = "btnAdd"; this.btnAdd.Size = new System.Drawing.Size(100, 36); this.btnAdd.TabIndex = 5; this.btnAdd.Text = "Добавить"; this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click); // // btnUpdate // this.btnUpdate.BorderRadius = 8; this.btnUpdate.FillColor = System.Drawing.Color.FromArgb(255, 193, 7); this.btnUpdate.Font = new System.Drawing.Font("Segoe UI", 9F); this.btnUpdate.ForeColor = System.Drawing.Color.Black; this.btnUpdate.Location = new System.Drawing.Point(520, 20); this.btnUpdate.Name = "btnUpdate"; this.btnUpdate.Size = new System.Drawing.Size(100, 36); this.btnUpdate.TabIndex = 6; this.btnUpdate.Text = "Обновить"; this.btnUpdate.Click += new System.EventHandler(this.btnUpdate_Click); // // btnDelete // this.btnDelete.BorderRadius = 8; this.btnDelete.FillColor = System.Drawing.Color.FromArgb(220, 53, 69); this.btnDelete.Font = new System.Drawing.Font("Segoe UI", 9F); this.btnDelete.ForeColor = System.Drawing.Color.White; this.btnDelete.Location = new System.Drawing.Point(640, 20); this.btnDelete.Name = "btnDelete"; this.btnDelete.Size = new System.Drawing.Size(100, 36); this.btnDelete.TabIndex = 7; this.btnDelete.Text = "Удалить"; this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click); // // btnRefresh // this.btnRefresh.BorderRadius = 8; this.btnRefresh.FillColor = System.Drawing.Color.FromArgb(52, 73, 94); this.btnRefresh.Font = new System.Drawing.Font("Segoe UI", 9F); this.btnRefresh.ForeColor = System.Drawing.Color.White; this.btnRefresh.Location = new System.Drawing.Point(400, 70); this.btnRefresh.Name = "btnRefresh"; this.btnRefresh.Size = new System.Drawing.Size(100, 36); this.btnRefresh.TabIndex = 8; this.btnRefresh.Text = "Обновить список"; this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click); // // lblUsername // this.lblUsername.BackColor = System.Drawing.Color.Transparent; this.lblUsername.Location = new System.Drawing.Point(20, 32); this.lblUsername.Name = "lblUsername"; this.lblUsername.Size = new System.Drawing.Size(37, 15); this.lblUsername.TabIndex = 9; this.lblUsername.Text = "Логин:"; // // lblPassword // this.lblPassword.BackColor = System.Drawing.Color.Transparent; this.lblPassword.Location = new System.Drawing.Point(20, 82); this.lblPassword.Name = "lblPassword"; this.lblPassword.Size = new System.Drawing.Size(44, 15); this.lblPassword.TabIndex = 10; this.lblPassword.Text = "Пароль:"; // // lblFullName // this.lblFullName.BackColor = System.Drawing.Color.Transparent; this.lblFullName.Location = new System.Drawing.Point(20, 132); this.lblFullName.Name = "lblFullName"; this.lblFullName.Size = new System.Drawing.Size(33, 15); this.lblFullName.TabIndex = 11; this.lblFullName.Text = "ФИО:"; // // lblRole // this.lblRole.BackColor = System.Drawing.Color.Transparent; this.lblRole.Location = new System.Drawing.Point(20, 182); this.lblRole.Name = "lblRole"; this.lblRole.Size = new System.Drawing.Size(31, 15); this.lblRole.TabIndex = 12; this.lblRole.Text = "Роль:"; // // UserManagementForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.FromArgb(240, 242, 245); this.ClientSize = new System.Drawing.Size(800, 500); this.Controls.Add(this.dgvUsers); this.Controls.Add(this.txtUsername); this.Controls.Add(this.txtPassword); this.Controls.Add(this.txtFullName); this.Controls.Add(this.cmbRole); this.Controls.Add(this.btnAdd); this.Controls.Add(this.btnUpdate); this.Controls.Add(this.btnDelete); this.Controls.Add(this.btnRefresh); this.Controls.Add(this.lblUsername); this.Controls.Add(this.lblPassword); this.Controls.Add(this.lblFullName); this.Controls.Add(this.lblRole); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.MaximizeBox = false; this.Name = "UserManagementForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Управление пользователями"; this.Load += new System.EventHandler(this.UserManagementForm_Load); ((System.ComponentModel.ISupportInitialize)(this.dgvUsers)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } } }