Lavig

UsersEdit

Apr 13th, 2026 (edited)
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 27.91 KB | None | 0 0
  1. using BCrypt.Net; // Підключення бібліотеки для хешування паролів
  2. using MySql.Data.MySqlClient; // Підключення драйвера для роботи з MySQL
  3. using System; // Базові системні класи
  4. using System.Data; // Робота з даними та таблицями
  5. using System.Drawing; // Робота з графікою (розміри, кольори)
  6. using System.Windows.Forms; // Бібліотека для створення віконного інтерфейсу
  7. using System.Text.RegularExpressions; // Робота з регулярними виразами
  8.  
  9. namespace lab8 // Оголошення простору імен проекту
  10. {
  11.     public partial class UsersEdit : Form // Оголошення класу форми редагування користувачів
  12.     {
  13.         string connectionString = "server=localhost;database=lab;uid=root;pwd=;"; // Рядок підключення до бази даних
  14.         int currentUserId = -1; // Змінна для зберігання ID поточного користувача (-1 означає створення нового)
  15.  
  16.         public UsersEdit(int id) // Конструктор форми, що приймає ID користувача
  17.         {
  18.             InitializeComponent(); // Ініціалізація компонентів інтерфейсу
  19.             currentUserId = id; // Присвоєння отриманого ID внутрішній змінній
  20.             Eye.ImageList = imageList1; // Прив'язка списку зображень до кнопки "око"
  21.             Eye.ImageIndex = 4; // Встановлення початкової іконки (закрите око)
  22.             Experience_Input.MaxLength = 200; // Обмеження довжини тексту в полі біографії
  23.         }
  24.  
  25.         private void UsersEdit_Load(object sender, EventArgs e) // Обробник події завантаження форми
  26.         {
  27.             LoadRoles(); // Виклик методу завантаження ролей у випадаючий список
  28.  
  29.             if (currentUserId == -1) // Перевірка: якщо ми додаємо нового користувача
  30.             {
  31.                 this.Text = "Додавання користувача"; // Зміна заголовка вікна
  32.                 Save.Text = " Додати"; // Зміна тексту на кнопці збереження
  33.                 Date_Input.Text = "Сформується автоматично"; // Підказка щодо дати реєстрації
  34.                 Date_Input.ForeColor = Color.Gray; // Встановлення сірого кольору для підказки
  35.             }
  36.             else // Якщо ми редагуємо існуючого користувача
  37.             {
  38.                 this.Text = "Редагування користувача (ID: " + currentUserId + ")"; // Вивід ID у заголовок
  39.                 LoadUserData(); // Виклик методу завантаження даних користувача з БД
  40.             }
  41.  
  42.             ToggleMentorFields(); // Налаштування видимості полів залежно від ролі
  43.         }
  44.  
  45.         private void LoadRoles() // Метод для отримання списку ролей з бази даних
  46.         {
  47.             MySqlConnection conn = new MySqlConnection(connectionString); // Створення об'єкта підключення
  48.             conn.Open(); // Відкриття з'єднання з БД
  49.  
  50.             string query = "SELECT id, role_name FROM roles"; // SQL-запит для отримання ролей
  51.             MySqlDataAdapter adapter = new MySqlDataAdapter(query, conn); // Адаптер для виконання запиту
  52.             DataTable dt = new DataTable(); // Створення таблиці в пам'яті
  53.             adapter.Fill(dt); // Заповнення таблиці даними з БД
  54.  
  55.             Role_Input.DataSource = dt; // Прив'язка таблиці до випадаючого списку
  56.             Role_Input.DisplayMember = "role_name"; // Відображення назви ролі користувачу
  57.             Role_Input.ValueMember = "id"; // Використання ID ролі як внутрішнього значення
  58.  
  59.             conn.Close(); // Закриття з'єднання
  60.         }
  61.  
  62.         private void ToggleMentorFields() // Метод керування видимістю додаткових полів ментора
  63.         {
  64.             bool isMentor = false; // Прапорець, чи є вибрана роль ментором
  65.             if (Role_Input.SelectedValue != null) // Перевірка, чи вибрано хоч якесь значення
  66.             {
  67.                 if (Role_Input.SelectedValue.ToString() == "2") // Якщо ID ролі дорівнює 2 (Ментор)
  68.                 {
  69.                     isMentor = true; // Встановлюємо прапорець у true
  70.                 }
  71.             }
  72.  
  73.             if (isMentor == true) // Якщо роль — ментор
  74.             {
  75.                 Mentor_Info.Visible = true; // Показати групу полів інформації ментора
  76.                 Experience_Info.Visible = true; // Показати групу полів досвіду
  77.                 this.Size = new Size(898, 566); // Розширити вікно форми
  78.             }
  79.             else // Якщо роль — звичайний користувач
  80.             {
  81.                 Mentor_Info.Visible = false; // Сховати поля ментора
  82.                 Experience_Info.Visible = false; // Сховати поля досвіду
  83.                 this.Size = new Size(463, 566); // Звузити вікно форми
  84.             }
  85.         }
  86.  
  87.         private void Role_Input_SelectedIndexChanged(object sender, EventArgs e) // Подія зміни ролі в списку
  88.         {
  89.             ToggleMentorFields(); // Перемикання видимості полів при зміні ролі
  90.         }
  91.  
  92.         private void LoadUserData() // Метод завантаження повної інформації про користувача для редагування
  93.         {
  94.             MySqlConnection conn = new MySqlConnection(connectionString); // Створення підключення
  95.             conn.Open(); // Відкриття з'єднання
  96.  
  97.             string query = "SELECT users.*, mentors.experience_years, mentors.biography, " +
  98.                 "mentors.website_url, mentors.linkedin_url, mentors.github_url " +
  99.                 "FROM users " +
  100.                 "LEFT JOIN mentors ON users.id = mentors.user_id " +
  101.                 "WHERE users.id = @id"; // SQL-запит з об'єднанням таблиць користувачів та менторів
  102.  
  103.             MySqlCommand cmd = new MySqlCommand(query, conn); // Створення команди
  104.             cmd.Parameters.AddWithValue("@id", currentUserId); // Безпечна передача параметра ID
  105.  
  106.             MySqlDataReader dr = cmd.ExecuteReader(); // Виконання запиту та створення читача даних
  107.  
  108.             if (dr.Read()) // Якщо запис знайдено
  109.             {
  110.                 Name_Input.Text = dr["full_name"].ToString(); // Заповнення поля ПІБ
  111.                 Email_Input.Text = dr["email"].ToString(); // Заповнення поля Email
  112.                 Role_Input.SelectedValue = dr["role_id"]; // Встановлення ролі в списку
  113.                 Date_Input.Text = dr["registration_date"].ToString(); // Вивід дати реєстрації
  114.  
  115.                 if (dr["phone"] == DBNull.Value) // Перевірка на відсутність номера телефону
  116.                 {
  117.                     Phone_Input.Text = ""; // Очищення поля, якщо в БД NULL
  118.                 }
  119.                 else
  120.                 {
  121.                     Phone_Input.Text = dr["phone"].ToString(); // Заповнення номера телефону
  122.                 }
  123.  
  124.                 if (dr["avatar_url"] == DBNull.Value) // Перевірка на відсутність посилання на аватар
  125.                 {
  126.                     Avatar_Input.Text = ""; // Очищення поля аватара
  127.                 }
  128.                 else
  129.                 {
  130.                     Avatar_Input.Text = dr["avatar_url"].ToString(); // Заповнення посилання
  131.                 }
  132.  
  133.                 bool isActive = Convert.ToBoolean(dr["is_active"]); // Отримання статусу активності
  134.                 if (isActive == true) // Якщо користувач активний
  135.                 {
  136.                     Active.Checked = true; // Вибір радіокнопки "Активний"
  137.                     Inactive.Checked = false; // Зняття вибору з "Неактивний"
  138.                 }
  139.                 else // Якщо заблокований
  140.                 {
  141.                     Active.Checked = false; // Зняття вибору з "Активний"
  142.                     Inactive.Checked = true; // Вибір радіокнопки "Неактивний"
  143.                 }
  144.  
  145.                 if (dr["experience_years"] == DBNull.Value) // Перевірка даних про роки досвіду
  146.                 {
  147.                     Years_Input.Value = 0; // Встановлення 0, якщо даних немає
  148.                 }
  149.                 else
  150.                 {
  151.                     Years_Input.Value = Convert.ToInt32(dr["experience_years"]); // Встановлення років досвіду
  152.                 }
  153.  
  154.                 if (dr["biography"] == DBNull.Value) // Перевірка наявності біографії
  155.                 {
  156.                     Experience_Input.Text = ""; // Очищення поля
  157.                 }
  158.                 else
  159.                 {
  160.                     Experience_Input.Text = dr["biography"].ToString(); // Заповнення біографії
  161.                 }
  162.  
  163.                 if (dr["website_url"] == DBNull.Value) // Перевірка посилання на сайт
  164.                 {
  165.                     Site_Input.Text = ""; // Очищення
  166.                 }
  167.                 else
  168.                 {
  169.                     Site_Input.Text = dr["website_url"].ToString(); // Заповнення сайту
  170.                 }
  171.  
  172.                 if (dr["linkedin_url"] == DBNull.Value) // Перевірка LinkedIn
  173.                 {
  174.                     Linkedin_Input.Text = ""; // Очищення
  175.                 }
  176.                 else
  177.                 {
  178.                     Linkedin_Input.Text = dr["linkedin_url"].ToString(); // Заповнення LinkedIn
  179.                 }
  180.  
  181.                 if (dr["github_url"] == DBNull.Value) // Перевірка GitHub
  182.                 {
  183.                     Github_Input.Text = ""; // Очищення
  184.                 }
  185.                 else
  186.                 {
  187.                     Github_Input.Text = dr["github_url"].ToString(); // Заповнення GitHub
  188.                 }
  189.             }
  190.  
  191.             dr.Close(); // Закриття читача
  192.             conn.Close(); // Закриття з'єднання
  193.         }
  194.  
  195.         private bool IsValidUrl(string url) // Метод валідації посилань
  196.         {
  197.             if (string.IsNullOrWhiteSpace(url)) // Якщо рядок порожній
  198.             {
  199.                 return true; // Вважаємо валідним (поле не обов'язкове)
  200.             }
  201.  
  202.             if (url.Trim().ToLower().StartsWith("http")) // Перевірка, чи починається з http/https
  203.             {
  204.                 return true; // Посилання коректне
  205.             }
  206.  
  207.             return false; // Посилання некоректне
  208.         }
  209.  
  210.         private void Save_Click(object sender, EventArgs e) // Головний метод збереження даних
  211.         {
  212.             if (Name_Input.Text == "" || Email_Input.Text == "") // Перевірка обов'язкових полів
  213.             {
  214.                 MessageBox.Show("Заповніть обов'язкові поля."); // Вивід попередження
  215.                 return; // Зупинка збереження
  216.             }
  217.  
  218.             if (currentUserId == -1) // Якщо створюється новий користувач
  219.             {
  220.                 if (Password_Input.Text == "") // Перевірка наявності пароля
  221.                 {
  222.                     MessageBox.Show("Введіть пароль для нового користувача."); // Повідомлення про відсутність пароля
  223.                     return; // Зупинка
  224.                 }
  225.  
  226.                 if (Password_Input.Text.Length < 8) // Перевірка мінімальної довжини
  227.                 {
  228.                     MessageBox.Show("Пароль має бути не менше 8 символів!"); // Попередження про короткий пароль
  229.                     return; // Зупинка
  230.                 }
  231.             }
  232.  
  233.             else if (Password_Input.Text != "" && Password_Input.Text.Length < 8) // При редагуванні, якщо пароль змінюється
  234.             {
  235.                 MessageBox.Show("Новий пароль має бути не менше 8 символів!"); // Попередження про довжину нового пароля
  236.                 return; // Зупинка
  237.             }
  238.  
  239.             var oldFormat = Phone_Input.TextMaskFormat; // Збереження поточного формату маски телефону
  240.             Phone_Input.TextMaskFormat = MaskFormat.ExcludePromptAndLiterals; // Налаштування для отримання тільки цифр
  241.             string plainPhone = Phone_Input.Text; // Отримання номера телефону без символів форматування
  242.             Phone_Input.TextMaskFormat = oldFormat; // Повернення формату маски назад
  243.  
  244.             if (plainPhone != "" && plainPhone != "380") // Перевірка, чи введено номер телефону
  245.             {
  246.                 if (Phone_Input.MaskFull == false) // Якщо маска заповнена не до кінця
  247.                 {
  248.                     MessageBox.Show("Номер телефону введено не повністю!"); // Попередження про неповний номер
  249.                     Phone_Input.Focus(); // Перевід фокусу на поле телефону
  250.                     return; // Зупинка
  251.                 }
  252.             }
  253.  
  254.             if (IsValidUrl(Avatar_Input.Text) == false) // Перевірка посилання на аватар
  255.             {
  256.                 MessageBox.Show("Некоректний URL аватара."); // Попередження про поганий URL
  257.                 return; // Зупинка
  258.             }
  259.  
  260.             bool isMentor = false; // Визначення, чи є користувач ментором
  261.             if (Role_Input.SelectedValue.ToString() == "2") // Якщо вибрано роль ID 2
  262.             {
  263.                 isMentor = true; // Встановлюємо статус ментора
  264.             }
  265.  
  266.             if (isMentor == true) // Якщо це ментор, перевіряємо його соцмережі
  267.             {
  268.                 if (IsValidUrl(Site_Input.Text) == false || IsValidUrl(Linkedin_Input.Text) == false || IsValidUrl(Github_Input.Text) == false)
  269.                 {
  270.                     MessageBox.Show("Перевірте правильність посилань."); // Попередження про помилки в URL ментора
  271.                     return; // Зупинка
  272.                 }
  273.             }
  274.  
  275.             MySqlConnection conn = new MySqlConnection(connectionString); // Створення з'єднання
  276.             conn.Open(); // Відкриття з'єднання
  277.  
  278.             string checkEmailQuery = "SELECT COUNT(*) FROM users WHERE email = @email AND id != @id"; // Запит на унікальність пошти
  279.             MySqlCommand checkCmd = new MySqlCommand(checkEmailQuery, conn); // Команда перевірки
  280.             checkCmd.Parameters.AddWithValue("@email", Email_Input.Text.Trim()); // Передача Email
  281.             checkCmd.Parameters.AddWithValue("@id", currentUserId); // Передача ID (щоб не сваритися на самого себе)
  282.  
  283.             int count = Convert.ToInt32(checkCmd.ExecuteScalar()); // Отримання кількості знайдених дублікатів
  284.             if (count > 0) // Якщо такий Email вже є в іншого користувача
  285.             {
  286.                 MessageBox.Show("Користувач з такою поштою вже існує!"); // Попередження про дублікат
  287.                 conn.Close(); // Закриття з'єднання
  288.                 return; // Зупинка
  289.             }
  290.  
  291.             MySqlTransaction trans = conn.BeginTransaction(); // Початок транзакції для цілісності даних
  292.             try
  293.             {
  294.                 string userQuery = ""; // Рядок для SQL запиту користувача
  295.                 if (currentUserId == -1) // Якщо це новий запис
  296.                 {
  297.                     userQuery = "INSERT INTO users (full_name, email, phone, role_id, avatar_url, is_active, password_hash) " +
  298.                                  "VALUES (@name, @email, @phone, @role, @avatar, @active, @pass); " +
  299.                                  "SELECT LAST_INSERT_ID();"; // Додавання та отримання згенерованого ID
  300.                 }
  301.                 else // Якщо це оновлення існуючого
  302.                 {
  303.                     userQuery = "UPDATE users SET full_name=@name, email=@email, phone=@phone, role_id=@role, " +
  304.                                  "avatar_url=@avatar, is_active=@active"; // Базова частина оновлення
  305.  
  306.                     if (Password_Input.Text != "") // Якщо поле пароля не порожнє (пароль змінюють)
  307.                     {
  308.                         userQuery = userQuery + ", password_hash=@pass"; // Додаємо оновлення пароля до запиту
  309.                     }
  310.                     userQuery = userQuery + " WHERE id=@id"; // Умова за ID
  311.                 }
  312.  
  313.                 MySqlCommand cmd = new MySqlCommand(userQuery, conn, trans); // Створення команди в межах транзакції
  314.                 cmd.Parameters.AddWithValue("@name", Name_Input.Text.Trim()); // Параметр імені
  315.                 cmd.Parameters.AddWithValue("@email", Email_Input.Text.Trim()); // Параметр Email
  316.                 cmd.Parameters.AddWithValue("@role", Role_Input.SelectedValue); // Параметр ролі
  317.  
  318.                 if (Active.Checked == true) // Визначення бітового значення активності
  319.                 {
  320.                     cmd.Parameters.AddWithValue("@active", 1); // Активний
  321.                 }
  322.                 else
  323.                 {
  324.                     cmd.Parameters.AddWithValue("@active", 0); // Неактивний
  325.                 }
  326.  
  327.                 if (Avatar_Input.Text == "") // Якщо посилання на аватар порожнє
  328.                 {
  329.                     cmd.Parameters.AddWithValue("@avatar", DBNull.Value); // Записуємо NULL в базу
  330.                 }
  331.                 else
  332.                 {
  333.                     cmd.Parameters.AddWithValue("@avatar", Avatar_Input.Text.Trim()); // Записуємо посилання
  334.                 }
  335.  
  336.                 if (plainPhone == "" || plainPhone == "380") // Якщо телефон не введено
  337.                 {
  338.                     cmd.Parameters.AddWithValue("@phone", DBNull.Value); // Записуємо NULL
  339.                 }
  340.                 else
  341.                 {
  342.                     cmd.Parameters.AddWithValue("@phone", Phone_Input.Text); // Записуємо повний номер з маскою
  343.                 }
  344.  
  345.                 if (Password_Input.Text != "") // Якщо потрібно зберегти пароль
  346.                 {
  347.                     string salt = BCrypt.Net.BCrypt.GenerateSalt(10); // Генерируємо "сіль" для безпеки
  348.                     string hashed = BCrypt.Net.BCrypt.HashPassword(Password_Input.Text, salt); // Хешуємо пароль
  349.                     cmd.Parameters.AddWithValue("@pass", hashed); // Передаємо хеш в параметри
  350.                 }
  351.  
  352.                 if (currentUserId != -1) // Для існуючого користувача
  353.                 {
  354.                     cmd.Parameters.AddWithValue("@id", currentUserId); // Встановлюємо ID
  355.                     cmd.ExecuteNonQuery(); // Виконуємо оновлення
  356.                 }
  357.                 else // Для нового користувача
  358.                 {
  359.                     currentUserId = Convert.ToInt32(cmd.ExecuteScalar()); // Виконуємо вставку та отримуємо новий ID
  360.                 }
  361.  
  362.                 if (isMentor == true) // Якщо користувач — ментор, оновлюємо додаткову таблицю
  363.                 {
  364.                     string deleteQuery = "DELETE FROM mentors WHERE user_id = @uid"; // Видаляємо старі дані ментора
  365.                     MySqlCommand dCmd = new MySqlCommand(deleteQuery, conn, trans); // Команда видалення
  366.                     dCmd.Parameters.AddWithValue("@uid", currentUserId); // Параметр ID
  367.                     dCmd.ExecuteNonQuery(); // Виконання видалення
  368.  
  369.                     string mentorQuery = "INSERT INTO mentors (user_id, experience_years, biography, website_url, linkedin_url, github_url) " +
  370.                                          "VALUES (@uid, @exp, @bio, @web, @link, @git)"; // Запит на додавання нових даних ментора
  371.  
  372.                     MySqlCommand mCmd = new MySqlCommand(mentorQuery, conn, trans); // Створення команди
  373.                     mCmd.Parameters.AddWithValue("@uid", currentUserId); // Параметр ID
  374.                     mCmd.Parameters.AddWithValue("@exp", Years_Input.Value); // Кількість років досвіду
  375.  
  376.                     if (Experience_Input.Text == "") // Обробка порожньої біографії
  377.                     {
  378.                         mCmd.Parameters.AddWithValue("@bio", DBNull.Value); // NULL
  379.                     }
  380.                     else
  381.                     {
  382.                         mCmd.Parameters.AddWithValue("@bio", Experience_Input.Text.Trim()); // Текст
  383.                     }
  384.  
  385.                     if (Site_Input.Text == "") // Обробка порожнього сайту
  386.                     {
  387.                         mCmd.Parameters.AddWithValue("@web", DBNull.Value); // NULL
  388.                     }
  389.                     else
  390.                     {
  391.                         mCmd.Parameters.AddWithValue("@web", Site_Input.Text.Trim()); // Текст
  392.                     }
  393.  
  394.                     if (Linkedin_Input.Text == "") // Обробка LinkedIn
  395.                     {
  396.                         mCmd.Parameters.AddWithValue("@link", DBNull.Value); // NULL
  397.                     }
  398.                     else
  399.                     {
  400.                         mCmd.Parameters.AddWithValue("@link", Linkedin_Input.Text.Trim()); // Текст
  401.                     }
  402.  
  403.                     if (Github_Input.Text == "") // Обробка GitHub
  404.                     {
  405.                         mCmd.Parameters.AddWithValue("@git", DBNull.Value); // NULL
  406.                     }
  407.                     else
  408.                     {
  409.                         mCmd.Parameters.AddWithValue("@git", Github_Input.Text.Trim()); // Текст
  410.                     }
  411.  
  412.                     mCmd.ExecuteNonQuery(); // Збереження даних ментора
  413.                 }
  414.  
  415.                 trans.Commit(); // Підтвердження транзакції (збереження всіх змін)
  416.                 this.DialogResult = DialogResult.OK; // Встановлення результату успіху для виклику форми
  417.                 this.Close(); // Закриття вікна
  418.             }
  419.             catch (Exception ex) // Обробка помилок
  420.             {
  421.                 trans.Rollback(); // Відкат усіх змін у разі помилки
  422.                 MessageBox.Show("Помилка збереження: " + ex.Message); // Повідомлення про помилку
  423.             }
  424.             conn.Close(); // Закриття з'єднання з БД
  425.         }
  426.  
  427.         private void Exit_Click(object sender, EventArgs e) // Обробник кнопки "Скасувати" або "Вихід"
  428.         {
  429.             this.Close(); // Закриття вікна без збереження
  430.         }
  431.  
  432.         private void Eye_Click(object sender, EventArgs e) // Керування видимістю пароля (кнопка з оком)
  433.         {
  434.             if (Password_Input.UseSystemPasswordChar == true) // Якщо пароль зараз прихований крапками
  435.             {
  436.                 Password_Input.UseSystemPasswordChar = false; // Показати символи пароля
  437.                 Eye.ImageIndex = 5; // Змінити іконку на відкрите око
  438.             }
  439.             else // Якщо пароль зараз видно
  440.             {
  441.                 Password_Input.UseSystemPasswordChar = true; // Сховати пароль крапками
  442.                 Eye.ImageIndex = 4; // Змінити іконку на закрите око
  443.             }
  444.         }
  445.  
  446.         private void Email_Input_Validating(object sender, System.ComponentModel.CancelEventArgs e) // Валідація Email при втраті фокусу
  447.         {
  448.             string pattern = @"^[^@\s]+@[^@\s]+\.[^@\s]+$"; // Регулярний вираз для перевірки формату пошти
  449.             if (Email_Input.Text != "") // Якщо поле не порожнє
  450.             {
  451.                 if (Regex.IsMatch(Email_Input.Text, pattern) == false) // Якщо текст не відповідає шаблону
  452.                 {
  453.                     MessageBox.Show("Введіть коректну адресу пошти."); // Повідомлення про помилку формату
  454.                     e.Cancel = true; // Заборона виходу з поля до виправлення помилки
  455.                 }
  456.             }
  457.         }
  458.  
  459.         private void OnlyLatin(object sender, KeyPressEventArgs e) // Обмеження вводу тільки латиницею
  460.         {
  461.             if (e.KeyChar > 127 || e.KeyChar == ' ') // Перевірка коду символу (ASCII) та заборона пробілів
  462.             {
  463.                 e.Handled = true; // Скасування введення забороненого символу
  464.             }
  465.         }
  466.     }
  467. }
Advertisement
Add Comment
Please, Sign In to add comment