UserManagementForm.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. using Guna.UI2.WinForms;
  2. using Npgsql;
  3. using System;
  4. using System.Data;
  5. using System.Threading.Tasks;
  6. using System.Windows.Forms;
  7. namespace DeanOfficeApp
  8. {
  9. public partial class UserManagementForm : Form
  10. {
  11. private Guna2DataGridView dgvUsers;
  12. private Guna2TextBox txtUsername, txtPassword, txtFullName;
  13. private Guna2ComboBox cmbRole;
  14. private Guna2Button btnAdd, btnUpdate, btnDelete, btnRefresh;
  15. private Guna2HtmlLabel lblUsername, lblPassword, lblFullName, lblRole;
  16. private readonly string _connString = "Host=245e1-rw.db.pub.dbaas.postgrespro.ru;Port=5432;Database=dbpractice;Username=mardasov_mv;Password=A4%2x$$2Ynr";
  17. public UserManagementForm()
  18. {
  19. InitializeComponent();
  20. this.Load += async (s, e) => await LoadUsersAsync();
  21. }
  22. // Асинхронная загрузка списка пользователей
  23. private async Task LoadUsersAsync()
  24. {
  25. try
  26. {
  27. Cursor = Cursors.WaitCursor;
  28. string sql = "SELECT user_id, username, role, full_name FROM appuser ORDER BY user_id";
  29. using (var conn = new NpgsqlConnection(_connString))
  30. {
  31. await conn.OpenAsync();
  32. using (var cmd = new NpgsqlCommand(sql, conn))
  33. {
  34. var dt = new DataTable();
  35. dt.Load(await cmd.ExecuteReaderAsync());
  36. dgvUsers.DataSource = dt;
  37. if (dgvUsers.Columns.Contains("user_id"))
  38. dgvUsers.Columns["user_id"].Visible = false;
  39. }
  40. }
  41. }
  42. catch (Exception ex)
  43. {
  44. MessageBox.Show($"Ошибка загрузки пользователей: {ex.Message}");
  45. }
  46. finally
  47. {
  48. Cursor = Cursors.Default;
  49. }
  50. }
  51. // Хеширование пароля через BCrypt
  52. private string HashPassword(string password) => BCrypt.Net.BCrypt.HashPassword(password);
  53. // Добавление нового пользователя
  54. private async void btnAdd_Click(object sender, EventArgs e)
  55. {
  56. string username = txtUsername.Text.Trim();
  57. string password = txtPassword.Text.Trim();
  58. string fullName = txtFullName.Text.Trim();
  59. string role = cmbRole.SelectedItem?.ToString();
  60. if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(role))
  61. {
  62. MessageBox.Show("Заполните логин, пароль и роль.");
  63. return;
  64. }
  65. string hash = HashPassword(password);
  66. string sql = "INSERT INTO appuser (username, password_hash, role, full_name) VALUES (@u, @p, @r, @f)";
  67. try
  68. {
  69. Cursor = Cursors.WaitCursor;
  70. using (var conn = new NpgsqlConnection(_connString))
  71. {
  72. await conn.OpenAsync();
  73. using (var cmd = new NpgsqlCommand(sql, conn))
  74. {
  75. cmd.Parameters.AddWithValue("@u", username);
  76. cmd.Parameters.AddWithValue("@p", hash);
  77. cmd.Parameters.AddWithValue("@r", role);
  78. cmd.Parameters.AddWithValue("@f", fullName);
  79. await cmd.ExecuteNonQueryAsync();
  80. }
  81. }
  82. await LoadUsersAsync();
  83. ClearFields();
  84. MessageBox.Show("Пользователь добавлен.");
  85. }
  86. catch (Exception ex)
  87. {
  88. MessageBox.Show($"Ошибка: {ex.Message}");
  89. }
  90. finally
  91. {
  92. Cursor = Cursors.Default;
  93. }
  94. }
  95. // Обновление данных пользователя
  96. private async void btnUpdate_Click(object sender, EventArgs e)
  97. {
  98. if (dgvUsers.CurrentRow == null)
  99. {
  100. MessageBox.Show("Выберите пользователя для обновления.");
  101. return;
  102. }
  103. int userId = (int)dgvUsers.CurrentRow.Cells["user_id"].Value;
  104. string username = txtUsername.Text.Trim();
  105. string password = txtPassword.Text.Trim();
  106. string fullName = txtFullName.Text.Trim();
  107. string role = cmbRole.SelectedItem?.ToString();
  108. if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(role))
  109. {
  110. MessageBox.Show("Заполните логин и роль.");
  111. return;
  112. }
  113. try
  114. {
  115. Cursor = Cursors.WaitCursor;
  116. using (var conn = new NpgsqlConnection(_connString))
  117. {
  118. await conn.OpenAsync();
  119. NpgsqlCommand cmd;
  120. if (!string.IsNullOrEmpty(password))
  121. {
  122. string hash = HashPassword(password);
  123. string sql = "UPDATE appuser SET username=@u, password_hash=@p, role=@r, full_name=@f WHERE user_id=@id";
  124. cmd = new NpgsqlCommand(sql, conn);
  125. cmd.Parameters.AddWithValue("@p", hash);
  126. }
  127. else
  128. {
  129. string sql = "UPDATE appuser SET username=@u, role=@r, full_name=@f WHERE user_id=@id";
  130. cmd = new NpgsqlCommand(sql, conn);
  131. }
  132. cmd.Parameters.AddWithValue("@u", username);
  133. cmd.Parameters.AddWithValue("@r", role);
  134. cmd.Parameters.AddWithValue("@f", fullName);
  135. cmd.Parameters.AddWithValue("@id", userId);
  136. await cmd.ExecuteNonQueryAsync();
  137. }
  138. await LoadUsersAsync();
  139. ClearFields();
  140. MessageBox.Show("Пользователь обновлён.");
  141. }
  142. catch (Exception ex)
  143. {
  144. MessageBox.Show($"Ошибка: {ex.Message}");
  145. }
  146. finally
  147. {
  148. Cursor = Cursors.Default;
  149. }
  150. }
  151. // Удаление пользователя
  152. private async void btnDelete_Click(object sender, EventArgs e)
  153. {
  154. if (dgvUsers.CurrentRow == null)
  155. {
  156. MessageBox.Show("Выберите пользователя для удаления.");
  157. return;
  158. }
  159. int userId = (int)dgvUsers.CurrentRow.Cells["user_id"].Value;
  160. if (MessageBox.Show("Удалить пользователя?", "Подтверждение", MessageBoxButtons.YesNo) != DialogResult.Yes)
  161. return;
  162. try
  163. {
  164. Cursor = Cursors.WaitCursor;
  165. using (var conn = new NpgsqlConnection(_connString))
  166. {
  167. await conn.OpenAsync();
  168. var cmd = new NpgsqlCommand("DELETE FROM appuser WHERE user_id=@id", conn);
  169. cmd.Parameters.AddWithValue("@id", userId);
  170. await cmd.ExecuteNonQueryAsync();
  171. }
  172. await LoadUsersAsync();
  173. ClearFields();
  174. MessageBox.Show("Пользователь удалён.");
  175. }
  176. catch (Exception ex)
  177. {
  178. MessageBox.Show($"Ошибка: {ex.Message}");
  179. }
  180. finally
  181. {
  182. Cursor = Cursors.Default;
  183. }
  184. }
  185. // Обновить список пользователей
  186. private async void btnRefresh_Click(object sender, EventArgs e)
  187. {
  188. await LoadUsersAsync();
  189. ClearFields();
  190. }
  191. // Заполнение полей при выборе строки в таблице
  192. private void dgvUsers_SelectionChanged(object sender, EventArgs e)
  193. {
  194. if (dgvUsers.CurrentRow != null)
  195. {
  196. txtUsername.Text = dgvUsers.CurrentRow.Cells["username"].Value.ToString();
  197. txtFullName.Text = dgvUsers.CurrentRow.Cells["full_name"].Value?.ToString() ?? "";
  198. string role = dgvUsers.CurrentRow.Cells["role"].Value.ToString();
  199. cmbRole.SelectedItem = role;
  200. txtPassword.Text = ""; // пароль не отображаем
  201. }
  202. }
  203. private void ClearFields()
  204. {
  205. txtUsername.Clear();
  206. txtPassword.Clear();
  207. txtFullName.Clear();
  208. cmbRole.SelectedIndex = -1;
  209. }
  210. // Пустой обработчик (можно удалить, но оставлен для совместимости)
  211. private void UserManagementForm_Load(object sender, EventArgs e) { }
  212. // ==================== ДИЗАЙНЕР ====================
  213. // Ниже расположен полный код InitializeComponent, сгенерированный конструктором.
  214. // Он должен быть идентичен вашему существующему, но я привожу его для полноты.
  215. private void InitializeComponent()
  216. {
  217. System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
  218. System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
  219. System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
  220. this.dgvUsers = new Guna.UI2.WinForms.Guna2DataGridView();
  221. this.txtUsername = new Guna.UI2.WinForms.Guna2TextBox();
  222. this.txtPassword = new Guna.UI2.WinForms.Guna2TextBox();
  223. this.txtFullName = new Guna.UI2.WinForms.Guna2TextBox();
  224. this.cmbRole = new Guna.UI2.WinForms.Guna2ComboBox();
  225. this.btnAdd = new Guna.UI2.WinForms.Guna2Button();
  226. this.btnUpdate = new Guna.UI2.WinForms.Guna2Button();
  227. this.btnDelete = new Guna.UI2.WinForms.Guna2Button();
  228. this.btnRefresh = new Guna.UI2.WinForms.Guna2Button();
  229. this.lblUsername = new Guna.UI2.WinForms.Guna2HtmlLabel();
  230. this.lblPassword = new Guna.UI2.WinForms.Guna2HtmlLabel();
  231. this.lblFullName = new Guna.UI2.WinForms.Guna2HtmlLabel();
  232. this.lblRole = new Guna.UI2.WinForms.Guna2HtmlLabel();
  233. ((System.ComponentModel.ISupportInitialize)(this.dgvUsers)).BeginInit();
  234. this.SuspendLayout();
  235. //
  236. // dgvUsers
  237. //
  238. this.dgvUsers.AllowUserToAddRows = false;
  239. this.dgvUsers.AllowUserToDeleteRows = false;
  240. dataGridViewCellStyle1.BackColor = System.Drawing.Color.White;
  241. this.dgvUsers.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1;
  242. dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
  243. dataGridViewCellStyle2.BackColor = System.Drawing.Color.FromArgb(100, 88, 255);
  244. dataGridViewCellStyle2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 204);
  245. dataGridViewCellStyle2.ForeColor = System.Drawing.Color.White;
  246. dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight;
  247. dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
  248. dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
  249. this.dgvUsers.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle2;
  250. this.dgvUsers.ColumnHeadersHeight = 40;
  251. dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
  252. dataGridViewCellStyle3.BackColor = System.Drawing.Color.White;
  253. dataGridViewCellStyle3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 204);
  254. dataGridViewCellStyle3.ForeColor = System.Drawing.Color.FromArgb(71, 69, 94);
  255. dataGridViewCellStyle3.SelectionBackColor = System.Drawing.Color.FromArgb(231, 229, 255);
  256. dataGridViewCellStyle3.SelectionForeColor = System.Drawing.Color.FromArgb(71, 69, 94);
  257. dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
  258. this.dgvUsers.DefaultCellStyle = dataGridViewCellStyle3;
  259. this.dgvUsers.GridColor = System.Drawing.Color.FromArgb(230, 230, 230);
  260. this.dgvUsers.Location = new System.Drawing.Point(20, 160);
  261. this.dgvUsers.Name = "dgvUsers";
  262. this.dgvUsers.ReadOnly = true;
  263. this.dgvUsers.RowHeadersVisible = false;
  264. this.dgvUsers.RowTemplate.Height = 30;
  265. this.dgvUsers.Size = new System.Drawing.Size(760, 320);
  266. this.dgvUsers.TabIndex = 0;
  267. this.dgvUsers.SelectionChanged += new System.EventHandler(this.dgvUsers_SelectionChanged);
  268. //
  269. // txtUsername
  270. //
  271. this.txtUsername.Cursor = System.Windows.Forms.Cursors.IBeam;
  272. this.txtUsername.DefaultText = "";
  273. this.txtUsername.Font = new System.Drawing.Font("Segoe UI", 9F);
  274. this.txtUsername.Location = new System.Drawing.Point(150, 20);
  275. this.txtUsername.Name = "txtUsername";
  276. this.txtUsername.PlaceholderText = "Логин";
  277. this.txtUsername.Size = new System.Drawing.Size(200, 36);
  278. this.txtUsername.TabIndex = 1;
  279. //
  280. // txtPassword
  281. //
  282. this.txtPassword.Cursor = System.Windows.Forms.Cursors.IBeam;
  283. this.txtPassword.DefaultText = "";
  284. this.txtPassword.Font = new System.Drawing.Font("Segoe UI", 9F);
  285. this.txtPassword.Location = new System.Drawing.Point(150, 70);
  286. this.txtPassword.Name = "txtPassword";
  287. this.txtPassword.PlaceholderText = "Пароль (оставьте пустым, чтобы не менять)";
  288. this.txtPassword.Size = new System.Drawing.Size(200, 36);
  289. this.txtPassword.TabIndex = 2;
  290. //
  291. // txtFullName
  292. //
  293. this.txtFullName.Cursor = System.Windows.Forms.Cursors.IBeam;
  294. this.txtFullName.DefaultText = "";
  295. this.txtFullName.Font = new System.Drawing.Font("Segoe UI", 9F);
  296. this.txtFullName.Location = new System.Drawing.Point(150, 120);
  297. this.txtFullName.Name = "txtFullName";
  298. this.txtFullName.PlaceholderText = "Полное имя";
  299. this.txtFullName.Size = new System.Drawing.Size(200, 36);
  300. this.txtFullName.TabIndex = 3;
  301. //
  302. // cmbRole
  303. //
  304. this.cmbRole.BackColor = System.Drawing.Color.Transparent;
  305. this.cmbRole.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
  306. this.cmbRole.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
  307. this.cmbRole.Font = new System.Drawing.Font("Segoe UI", 10F);
  308. this.cmbRole.ForeColor = System.Drawing.Color.FromArgb(68, 88, 112);
  309. this.cmbRole.ItemHeight = 30;
  310. this.cmbRole.Items.AddRange(new object[] { "admin", "manager", "teacher", "student" });
  311. this.cmbRole.Location = new System.Drawing.Point(150, 170);
  312. this.cmbRole.Name = "cmbRole";
  313. this.cmbRole.Size = new System.Drawing.Size(200, 36);
  314. this.cmbRole.TabIndex = 4;
  315. //
  316. // btnAdd
  317. //
  318. this.btnAdd.BorderRadius = 8;
  319. this.btnAdd.FillColor = System.Drawing.Color.FromArgb(40, 167, 69);
  320. this.btnAdd.Font = new System.Drawing.Font("Segoe UI", 9F);
  321. this.btnAdd.ForeColor = System.Drawing.Color.White;
  322. this.btnAdd.Location = new System.Drawing.Point(400, 20);
  323. this.btnAdd.Name = "btnAdd";
  324. this.btnAdd.Size = new System.Drawing.Size(100, 36);
  325. this.btnAdd.TabIndex = 5;
  326. this.btnAdd.Text = "Добавить";
  327. this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click);
  328. //
  329. // btnUpdate
  330. //
  331. this.btnUpdate.BorderRadius = 8;
  332. this.btnUpdate.FillColor = System.Drawing.Color.FromArgb(255, 193, 7);
  333. this.btnUpdate.Font = new System.Drawing.Font("Segoe UI", 9F);
  334. this.btnUpdate.ForeColor = System.Drawing.Color.Black;
  335. this.btnUpdate.Location = new System.Drawing.Point(520, 20);
  336. this.btnUpdate.Name = "btnUpdate";
  337. this.btnUpdate.Size = new System.Drawing.Size(100, 36);
  338. this.btnUpdate.TabIndex = 6;
  339. this.btnUpdate.Text = "Обновить";
  340. this.btnUpdate.Click += new System.EventHandler(this.btnUpdate_Click);
  341. //
  342. // btnDelete
  343. //
  344. this.btnDelete.BorderRadius = 8;
  345. this.btnDelete.FillColor = System.Drawing.Color.FromArgb(220, 53, 69);
  346. this.btnDelete.Font = new System.Drawing.Font("Segoe UI", 9F);
  347. this.btnDelete.ForeColor = System.Drawing.Color.White;
  348. this.btnDelete.Location = new System.Drawing.Point(640, 20);
  349. this.btnDelete.Name = "btnDelete";
  350. this.btnDelete.Size = new System.Drawing.Size(100, 36);
  351. this.btnDelete.TabIndex = 7;
  352. this.btnDelete.Text = "Удалить";
  353. this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
  354. //
  355. // btnRefresh
  356. //
  357. this.btnRefresh.BorderRadius = 8;
  358. this.btnRefresh.FillColor = System.Drawing.Color.FromArgb(52, 73, 94);
  359. this.btnRefresh.Font = new System.Drawing.Font("Segoe UI", 9F);
  360. this.btnRefresh.ForeColor = System.Drawing.Color.White;
  361. this.btnRefresh.Location = new System.Drawing.Point(400, 70);
  362. this.btnRefresh.Name = "btnRefresh";
  363. this.btnRefresh.Size = new System.Drawing.Size(100, 36);
  364. this.btnRefresh.TabIndex = 8;
  365. this.btnRefresh.Text = "Обновить список";
  366. this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
  367. //
  368. // lblUsername
  369. //
  370. this.lblUsername.BackColor = System.Drawing.Color.Transparent;
  371. this.lblUsername.Location = new System.Drawing.Point(20, 32);
  372. this.lblUsername.Name = "lblUsername";
  373. this.lblUsername.Size = new System.Drawing.Size(37, 15);
  374. this.lblUsername.TabIndex = 9;
  375. this.lblUsername.Text = "Логин:";
  376. //
  377. // lblPassword
  378. //
  379. this.lblPassword.BackColor = System.Drawing.Color.Transparent;
  380. this.lblPassword.Location = new System.Drawing.Point(20, 82);
  381. this.lblPassword.Name = "lblPassword";
  382. this.lblPassword.Size = new System.Drawing.Size(44, 15);
  383. this.lblPassword.TabIndex = 10;
  384. this.lblPassword.Text = "Пароль:";
  385. //
  386. // lblFullName
  387. //
  388. this.lblFullName.BackColor = System.Drawing.Color.Transparent;
  389. this.lblFullName.Location = new System.Drawing.Point(20, 132);
  390. this.lblFullName.Name = "lblFullName";
  391. this.lblFullName.Size = new System.Drawing.Size(33, 15);
  392. this.lblFullName.TabIndex = 11;
  393. this.lblFullName.Text = "ФИО:";
  394. //
  395. // lblRole
  396. //
  397. this.lblRole.BackColor = System.Drawing.Color.Transparent;
  398. this.lblRole.Location = new System.Drawing.Point(20, 182);
  399. this.lblRole.Name = "lblRole";
  400. this.lblRole.Size = new System.Drawing.Size(31, 15);
  401. this.lblRole.TabIndex = 12;
  402. this.lblRole.Text = "Роль:";
  403. //
  404. // UserManagementForm
  405. //
  406. this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
  407. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  408. this.BackColor = System.Drawing.Color.FromArgb(240, 242, 245);
  409. this.ClientSize = new System.Drawing.Size(800, 500);
  410. this.Controls.Add(this.dgvUsers);
  411. this.Controls.Add(this.txtUsername);
  412. this.Controls.Add(this.txtPassword);
  413. this.Controls.Add(this.txtFullName);
  414. this.Controls.Add(this.cmbRole);
  415. this.Controls.Add(this.btnAdd);
  416. this.Controls.Add(this.btnUpdate);
  417. this.Controls.Add(this.btnDelete);
  418. this.Controls.Add(this.btnRefresh);
  419. this.Controls.Add(this.lblUsername);
  420. this.Controls.Add(this.lblPassword);
  421. this.Controls.Add(this.lblFullName);
  422. this.Controls.Add(this.lblRole);
  423. this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
  424. this.MaximizeBox = false;
  425. this.Name = "UserManagementForm";
  426. this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
  427. this.Text = "Управление пользователями";
  428. this.Load += new System.EventHandler(this.UserManagementForm_Load);
  429. ((System.ComponentModel.ISupportInitialize)(this.dgvUsers)).EndInit();
  430. this.ResumeLayout(false);
  431. this.PerformLayout();
  432. }
  433. }
  434. }