From b81b059177b3de7316caa02780934528d862cf3b Mon Sep 17 00:00:00 2001 From: Moonbase Date: Sun, 27 Jul 2025 13:51:44 -0700 Subject: [PATCH 1/2] Initial Implementation Of Email Features --- QtCNETAPI/Dtos/User/UserPasswordResetDto.cs | 14 ++ QtCNETAPI/Services/ApiService/ApiService.cs | 66 ++++++ QtCNETAPI/Services/ApiService/IApiService.cs | 3 + qtc-net-client-2/Forms/Login.Designer.cs | 64 +++-- qtc-net-client-2/Forms/Login.cs | 28 ++- qtc-net-client-2/Forms/Main.cs | 4 +- .../Forms/ResendVerificationEmail.Designer.cs | 104 +++++++++ .../Forms/ResendVerificationEmail.cs | 43 ++++ .../Forms/ResendVerificationEmail.resx | 120 ++++++++++ .../Forms/ResetPassword.Designer.cs | 221 ++++++++++++++++++ qtc-net-client-2/Forms/ResetPassword.cs | 68 ++++++ qtc-net-client-2/Forms/ResetPassword.resx | 120 ++++++++++ 12 files changed, 829 insertions(+), 26 deletions(-) create mode 100644 QtCNETAPI/Dtos/User/UserPasswordResetDto.cs create mode 100644 qtc-net-client-2/Forms/ResendVerificationEmail.Designer.cs create mode 100644 qtc-net-client-2/Forms/ResendVerificationEmail.cs create mode 100644 qtc-net-client-2/Forms/ResendVerificationEmail.resx create mode 100644 qtc-net-client-2/Forms/ResetPassword.Designer.cs create mode 100644 qtc-net-client-2/Forms/ResetPassword.cs create mode 100644 qtc-net-client-2/Forms/ResetPassword.resx diff --git a/QtCNETAPI/Dtos/User/UserPasswordResetDto.cs b/QtCNETAPI/Dtos/User/UserPasswordResetDto.cs new file mode 100644 index 0000000..3436077 --- /dev/null +++ b/QtCNETAPI/Dtos/User/UserPasswordResetDto.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QtCNETAPI.Dtos.User +{ + public class UserPasswordResetDto + { + public string Token { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; + } +} diff --git a/QtCNETAPI/Services/ApiService/ApiService.cs b/QtCNETAPI/Services/ApiService/ApiService.cs index 5d625ee..6c714ef 100644 --- a/QtCNETAPI/Services/ApiService/ApiService.cs +++ b/QtCNETAPI/Services/ApiService/ApiService.cs @@ -280,6 +280,72 @@ namespace QtCNETAPI.Services.ApiService return serviceResponse; } + public async Task> ResendVerificationEmail(string email) + { + var serviceResponse = new ServiceResponse(); + + var restRequest = new RestRequest($"auth/resend-verification-email") + .AddQueryParameter("email", email); + var response = await _client.PostAsync>(restRequest); + + if (response != null) + { + serviceResponse.Success = true; + serviceResponse.Data = response.Data; + } + else + { + serviceResponse.Success = false; + serviceResponse.Message = "API never responded."; + } + + return serviceResponse; + } + + public async Task> SendPasswordResetEmail(string email) + { + var serviceResponse = new ServiceResponse(); + + var restRequest = new RestRequest($"auth/request-password-reset") + .AddQueryParameter("email", email); + var response = await _client.PostAsync>(restRequest); + + if (response != null) + { + serviceResponse.Success = true; + serviceResponse.Data = response.Data; + } + else + { + serviceResponse.Success = false; + serviceResponse.Message = "API never responded."; + } + + return serviceResponse; + } + + public async Task> ResetPassword(UserPasswordResetDto request) + { + var serviceResponse = new ServiceResponse(); + + var restRequest = new RestRequest($"auth/reset-password") + .AddJsonBody(request); + var response = await _client.PostAsync>(restRequest); + + if (response != null) + { + serviceResponse.Success = true; + serviceResponse.Data = response.Data; + } + else + { + serviceResponse.Success = false; + serviceResponse.Message = "API never responded."; + } + + return serviceResponse; + } + public async Task SetCurrentUser() { var userRequest = new RestRequest("users/user-authorized") diff --git a/QtCNETAPI/Services/ApiService/IApiService.cs b/QtCNETAPI/Services/ApiService/IApiService.cs index 0e3b571..0af2644 100644 --- a/QtCNETAPI/Services/ApiService/IApiService.cs +++ b/QtCNETAPI/Services/ApiService/IApiService.cs @@ -24,6 +24,9 @@ namespace QtCNETAPI.Services.ApiService public Task>> GetAllUsersAsync(); public Task> DeleteUserById(string id); public Task> LoginAsync(UserLoginDto userLoginDto); + public Task> ResendVerificationEmail(string email); + public Task> SendPasswordResetEmail(string email); + public Task> ResetPassword(UserPasswordResetDto request); public Task> RefreshLogin(string refreshToken); public Task> RefreshSessionIfInvalid(); public Task SetCurrentUser(); diff --git a/qtc-net-client-2/Forms/Login.Designer.cs b/qtc-net-client-2/Forms/Login.Designer.cs index f352484..a26fa0d 100644 --- a/qtc-net-client-2/Forms/Login.Designer.cs +++ b/qtc-net-client-2/Forms/Login.Designer.cs @@ -1,6 +1,6 @@ namespace qtc_net_client_2.Forms { - partial class Login + partial class llblForgotPassword { /// /// Required designer variable. @@ -28,15 +28,17 @@ /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Login)); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(llblForgotPassword)); pbLoginBanner = new PictureBox(); tbEmail = new TextBox(); lblEmail = new Label(); - label1 = new Label(); + lblPassword = new Label(); tbPassword = new TextBox(); btnLogin = new Button(); llblRegister = new LinkLabel(); cbRememberMe = new CheckBox(); + llblResendEmail = new LinkLabel(); + llblForgotPasswor = new LinkLabel(); ((System.ComponentModel.ISupportInitialize)pbLoginBanner).BeginInit(); SuspendLayout(); // @@ -68,16 +70,16 @@ lblEmail.TabIndex = 2; lblEmail.Text = "Email"; // - // label1 + // lblPassword // - label1.AutoSize = true; - label1.Font = new Font("Segoe UI Light", 9F); - label1.ForeColor = SystemColors.ControlLight; - label1.Location = new Point(11, 138); - label1.Name = "label1"; - label1.Size = new Size(55, 15); - label1.TabIndex = 4; - label1.Text = "Password"; + lblPassword.AutoSize = true; + lblPassword.Font = new Font("Segoe UI Light", 9F); + lblPassword.ForeColor = SystemColors.ControlLight; + lblPassword.Location = new Point(11, 138); + lblPassword.Name = "lblPassword"; + lblPassword.Size = new Size(55, 15); + lblPassword.TabIndex = 4; + lblPassword.Text = "Password"; // // tbPassword // @@ -122,16 +124,44 @@ cbRememberMe.Text = "Remember Me For 7 Days"; cbRememberMe.UseVisualStyleBackColor = true; // - // frmLogin + // llblResendEmail + // + llblResendEmail.AutoSize = true; + llblResendEmail.Font = new Font("Segoe UI Light", 9F); + llblResendEmail.LinkColor = SystemColors.ControlLight; + llblResendEmail.Location = new Point(369, 164); + llblResendEmail.Name = "llblResendEmail"; + llblResendEmail.Size = new Size(129, 15); + llblResendEmail.TabIndex = 8; + llblResendEmail.TabStop = true; + llblResendEmail.Text = "Resend Verification Email"; + llblResendEmail.LinkClicked += llblResendEmail_LinkClicked; + // + // llblForgotPasswor + // + llblForgotPasswor.AutoSize = true; + llblForgotPasswor.Font = new Font("Segoe UI Light", 9F); + llblForgotPasswor.LinkColor = SystemColors.ControlLight; + llblForgotPasswor.Location = new Point(401, 181); + llblForgotPasswor.Name = "llblForgotPasswor"; + llblForgotPasswor.Size = new Size(98, 15); + llblForgotPasswor.TabIndex = 9; + llblForgotPasswor.TabStop = true; + llblForgotPasswor.Text = "Forgot Password?"; + llblForgotPasswor.LinkClicked += llblForgotPasswor_LinkClicked; + // + // llblForgotPassword // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; BackColor = Color.DodgerBlue; ClientSize = new Size(515, 203); + Controls.Add(llblForgotPasswor); + Controls.Add(llblResendEmail); Controls.Add(cbRememberMe); Controls.Add(llblRegister); Controls.Add(btnLogin); - Controls.Add(label1); + Controls.Add(lblPassword); Controls.Add(tbPassword); Controls.Add(lblEmail); Controls.Add(tbEmail); @@ -139,7 +169,7 @@ FormBorderStyle = FormBorderStyle.FixedDialog; Icon = (Icon)resources.GetObject("$this.Icon"); MaximizeBox = false; - Name = "frmLogin"; + Name = "llblForgotPassword"; StartPosition = FormStartPosition.CenterParent; Text = "QtC.NET Client - Login"; Load += frmLogin_Load; @@ -153,10 +183,12 @@ private PictureBox pbLoginBanner; private TextBox tbEmail; private Label lblEmail; - private Label label1; + private Label lblPassword; private TextBox tbPassword; private Button btnLogin; private LinkLabel llblRegister; private CheckBox cbRememberMe; + private LinkLabel llblResendEmail; + private LinkLabel llblForgotPasswor; } } \ No newline at end of file diff --git a/qtc-net-client-2/Forms/Login.cs b/qtc-net-client-2/Forms/Login.cs index 39320a7..828fec0 100644 --- a/qtc-net-client-2/Forms/Login.cs +++ b/qtc-net-client-2/Forms/Login.cs @@ -12,10 +12,10 @@ using System.Windows.Forms; namespace qtc_net_client_2.Forms { - public partial class Login : Form + public partial class llblForgotPassword : Form { private IApiService _apiService; - public Login(IApiService apiService) + public llblForgotPassword(IApiService apiService) { _apiService = apiService; @@ -68,6 +68,24 @@ namespace qtc_net_client_2.Forms } } + private void llblRegister_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + Register frmRegister = new Register(_apiService); + frmRegister.ShowDialog(); + } + + private void llblResendEmail_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + ResendVerificationEmail resendVerificationEmail = new ResendVerificationEmail(_apiService); + resendVerificationEmail.ShowDialog(); + } + + private void llblForgotPasswor_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + ResetPassword resetPassword = new ResetPassword(_apiService); + resetPassword.ShowDialog(); + } + private void ToggleControls(bool enable, bool clearText) { tbEmail.Enabled = enable; @@ -81,11 +99,5 @@ namespace qtc_net_client_2.Forms tbPassword.Text = string.Empty; } } - - private void llblRegister_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - Register frmRegister = new Register(_apiService); - frmRegister.ShowDialog(); - } } } diff --git a/qtc-net-client-2/Forms/Main.cs b/qtc-net-client-2/Forms/Main.cs index 7c4fce3..389ef0b 100644 --- a/qtc-net-client-2/Forms/Main.cs +++ b/qtc-net-client-2/Forms/Main.cs @@ -49,7 +49,7 @@ namespace qtc_net_client_2 if (_apiService.CurrentUser == null) { // not logged in, load the login form - Login frmLogin = new Login(_apiService); + llblForgotPassword frmLogin = new llblForgotPassword(_apiService); var result = frmLogin.ShowDialog(); if (result == DialogResult.OK) @@ -60,7 +60,7 @@ namespace qtc_net_client_2 private async void llblSignIn_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { // just reshow the login dialog lol - Login frmLogin = new Login(_apiService); + llblForgotPassword frmLogin = new llblForgotPassword(_apiService); var result = frmLogin.ShowDialog(); if (result == DialogResult.OK) diff --git a/qtc-net-client-2/Forms/ResendVerificationEmail.Designer.cs b/qtc-net-client-2/Forms/ResendVerificationEmail.Designer.cs new file mode 100644 index 0000000..3bfb3dd --- /dev/null +++ b/qtc-net-client-2/Forms/ResendVerificationEmail.Designer.cs @@ -0,0 +1,104 @@ +namespace qtc_net_client_2.Forms +{ + partial class ResendVerificationEmail + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + pbLoginBanner = new PictureBox(); + tbEmail = new TextBox(); + lblHeader = new Label(); + btnSend = new Button(); + ((System.ComponentModel.ISupportInitialize)pbLoginBanner).BeginInit(); + SuspendLayout(); + // + // pbLoginBanner + // + pbLoginBanner.Image = Properties.Resources.LoginBanner; + pbLoginBanner.Location = new Point(-4, 0); + pbLoginBanner.Name = "pbLoginBanner"; + pbLoginBanner.Size = new Size(521, 99); + pbLoginBanner.SizeMode = PictureBoxSizeMode.StretchImage; + pbLoginBanner.TabIndex = 1; + pbLoginBanner.TabStop = false; + // + // tbEmail + // + tbEmail.Location = new Point(50, 124); + tbEmail.Name = "tbEmail"; + tbEmail.Size = new Size(424, 23); + tbEmail.TabIndex = 3; + // + // lblHeader + // + lblHeader.AutoSize = true; + lblHeader.Font = new Font("Segoe UI Light", 9F); + lblHeader.ForeColor = SystemColors.ControlLight; + lblHeader.Location = new Point(54, 106); + lblHeader.Name = "lblHeader"; + lblHeader.Size = new Size(412, 15); + lblHeader.TabIndex = 5; + lblHeader.Text = "Please Enter Your Email, If An Account Exists With This Email, We'll Send You A Link"; + // + // btnSend + // + btnSend.Location = new Point(224, 153); + btnSend.Name = "btnSend"; + btnSend.Size = new Size(75, 23); + btnSend.TabIndex = 6; + btnSend.Text = "Send"; + btnSend.UseVisualStyleBackColor = true; + btnSend.Click += btnSend_Click; + // + // ResendVerificationEmail + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + BackColor = Color.DodgerBlue; + ClientSize = new Size(515, 187); + Controls.Add(btnSend); + Controls.Add(lblHeader); + Controls.Add(tbEmail); + Controls.Add(pbLoginBanner); + FormBorderStyle = FormBorderStyle.FixedDialog; + MaximizeBox = false; + MinimizeBox = false; + Name = "ResendVerificationEmail"; + StartPosition = FormStartPosition.CenterScreen; + Text = "QtC.NET Client - Resend Verification Email"; + ((System.ComponentModel.ISupportInitialize)pbLoginBanner).EndInit(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private PictureBox pbLoginBanner; + private TextBox tbEmail; + private Label lblHeader; + private Button btnSend; + } +} \ No newline at end of file diff --git a/qtc-net-client-2/Forms/ResendVerificationEmail.cs b/qtc-net-client-2/Forms/ResendVerificationEmail.cs new file mode 100644 index 0000000..3c95e1f --- /dev/null +++ b/qtc-net-client-2/Forms/ResendVerificationEmail.cs @@ -0,0 +1,43 @@ +using QtCNETAPI.Services.ApiService; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace qtc_net_client_2.Forms +{ + public partial class ResendVerificationEmail : Form + { + private IApiService _apiService; + public ResendVerificationEmail(IApiService apiService) + { + _apiService = apiService; + InitializeComponent(); + } + + private async void btnSend_Click(object sender, EventArgs e) + { + if(!string.IsNullOrEmpty(tbEmail.Text)) + { + tbEmail.Enabled = false; + btnSend.Enabled = false; + + var result = await _apiService.ResendVerificationEmail(tbEmail.Text); + if(result != null && result.Success && result.Data) + { + MessageBox.Show("Got It! You should receive an email shortly.\nIf you do not receive an email, check your spam.", "", MessageBoxButtons.OK, MessageBoxIcon.Information); + Close(); + } else + { + MessageBox.Show("Sorry, This Server Doesn't Have Email Features Enabled Or Something Went Wrong.\nIf you cannot login, you may need to contact the server admin.", "", MessageBoxButtons.OK, MessageBoxIcon.Error); + Close(); + } + } + } + } +} diff --git a/qtc-net-client-2/Forms/ResendVerificationEmail.resx b/qtc-net-client-2/Forms/ResendVerificationEmail.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/qtc-net-client-2/Forms/ResendVerificationEmail.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/qtc-net-client-2/Forms/ResetPassword.Designer.cs b/qtc-net-client-2/Forms/ResetPassword.Designer.cs new file mode 100644 index 0000000..2866519 --- /dev/null +++ b/qtc-net-client-2/Forms/ResetPassword.Designer.cs @@ -0,0 +1,221 @@ +namespace qtc_net_client_2.Forms +{ + partial class ResetPassword + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + pEmailBox = new Panel(); + btnSend = new Button(); + lblHeader = new Label(); + tbEmail = new TextBox(); + pResetPasswordBox = new Panel(); + btnResetPassword = new Button(); + tbConfirmPassword = new TextBox(); + lblConfirmPassword = new Label(); + tbNewPassword = new TextBox(); + lblNewPassword = new Label(); + tbToken = new TextBox(); + lblToken = new Label(); + pbLoginBanner = new PictureBox(); + pEmailBox.SuspendLayout(); + pResetPasswordBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)pbLoginBanner).BeginInit(); + SuspendLayout(); + // + // pEmailBox + // + pEmailBox.Anchor = AnchorStyles.Bottom; + pEmailBox.BorderStyle = BorderStyle.FixedSingle; + pEmailBox.Controls.Add(btnSend); + pEmailBox.Controls.Add(lblHeader); + pEmailBox.Controls.Add(tbEmail); + pEmailBox.Location = new Point(101, 125); + pEmailBox.Name = "pEmailBox"; + pEmailBox.Size = new Size(458, 94); + pEmailBox.TabIndex = 0; + // + // btnSend + // + btnSend.Location = new Point(193, 59); + btnSend.Name = "btnSend"; + btnSend.Size = new Size(75, 23); + btnSend.TabIndex = 9; + btnSend.Text = "Send"; + btnSend.UseVisualStyleBackColor = true; + btnSend.Click += btnSend_Click; + // + // lblHeader + // + lblHeader.AutoSize = true; + lblHeader.Font = new Font("Segoe UI Light", 9F); + lblHeader.ForeColor = SystemColors.ControlLight; + lblHeader.Location = new Point(23, 12); + lblHeader.Name = "lblHeader"; + lblHeader.Size = new Size(412, 15); + lblHeader.TabIndex = 8; + lblHeader.Text = "Please Enter Your Email, If An Account Exists With This Email, We'll Send You A Link"; + // + // tbEmail + // + tbEmail.Location = new Point(19, 30); + tbEmail.Name = "tbEmail"; + tbEmail.Size = new Size(424, 23); + tbEmail.TabIndex = 7; + // + // pResetPasswordBox + // + pResetPasswordBox.Anchor = AnchorStyles.Bottom; + pResetPasswordBox.BorderStyle = BorderStyle.FixedSingle; + pResetPasswordBox.Controls.Add(btnResetPassword); + pResetPasswordBox.Controls.Add(tbConfirmPassword); + pResetPasswordBox.Controls.Add(lblConfirmPassword); + pResetPasswordBox.Controls.Add(tbNewPassword); + pResetPasswordBox.Controls.Add(lblNewPassword); + pResetPasswordBox.Controls.Add(tbToken); + pResetPasswordBox.Controls.Add(lblToken); + pResetPasswordBox.Location = new Point(17, 106); + pResetPasswordBox.Name = "pResetPasswordBox"; + pResetPasswordBox.Size = new Size(596, 138); + pResetPasswordBox.TabIndex = 1; + pResetPasswordBox.Visible = false; + // + // btnResetPassword + // + btnResetPassword.Location = new Point(270, 102); + btnResetPassword.Name = "btnResetPassword"; + btnResetPassword.Size = new Size(100, 23); + btnResetPassword.TabIndex = 15; + btnResetPassword.Text = "Reset Password"; + btnResetPassword.UseVisualStyleBackColor = true; + btnResetPassword.Click += btnResetPassword_Click; + // + // tbConfirmPassword + // + tbConfirmPassword.Location = new Point(123, 73); + tbConfirmPassword.Name = "tbConfirmPassword"; + tbConfirmPassword.PasswordChar = '*'; + tbConfirmPassword.Size = new Size(424, 23); + tbConfirmPassword.TabIndex = 14; + // + // lblConfirmPassword + // + lblConfirmPassword.AutoSize = true; + lblConfirmPassword.Font = new Font("Segoe UI Light", 9F); + lblConfirmPassword.ForeColor = SystemColors.ControlLight; + lblConfirmPassword.Location = new Point(20, 76); + lblConfirmPassword.Name = "lblConfirmPassword"; + lblConfirmPassword.Size = new Size(97, 15); + lblConfirmPassword.TabIndex = 13; + lblConfirmPassword.Text = "Confirm Password"; + // + // tbNewPassword + // + tbNewPassword.Location = new Point(123, 44); + tbNewPassword.Name = "tbNewPassword"; + tbNewPassword.PasswordChar = '*'; + tbNewPassword.Size = new Size(424, 23); + tbNewPassword.TabIndex = 12; + // + // lblNewPassword + // + lblNewPassword.AutoSize = true; + lblNewPassword.Font = new Font("Segoe UI Light", 9F); + lblNewPassword.ForeColor = SystemColors.ControlLight; + lblNewPassword.Location = new Point(36, 47); + lblNewPassword.Name = "lblNewPassword"; + lblNewPassword.Size = new Size(81, 15); + lblNewPassword.TabIndex = 11; + lblNewPassword.Text = "New Password"; + // + // tbToken + // + tbToken.Location = new Point(123, 15); + tbToken.Name = "tbToken"; + tbToken.Size = new Size(424, 23); + tbToken.TabIndex = 10; + // + // lblToken + // + lblToken.AutoSize = true; + lblToken.Font = new Font("Segoe UI Light", 9F); + lblToken.ForeColor = SystemColors.ControlLight; + lblToken.Location = new Point(82, 18); + lblToken.Name = "lblToken"; + lblToken.Size = new Size(35, 15); + lblToken.TabIndex = 9; + lblToken.Text = "Token"; + // + // pbLoginBanner + // + pbLoginBanner.Image = Properties.Resources.LoginBanner; + pbLoginBanner.Location = new Point(-3, -1); + pbLoginBanner.Name = "pbLoginBanner"; + pbLoginBanner.Size = new Size(521, 99); + pbLoginBanner.SizeMode = PictureBoxSizeMode.StretchImage; + pbLoginBanner.TabIndex = 2; + pbLoginBanner.TabStop = false; + // + // ResetPassword + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + BackColor = Color.DodgerBlue; + ClientSize = new Size(622, 256); + Controls.Add(pEmailBox); + Controls.Add(pResetPasswordBox); + Controls.Add(pbLoginBanner); + FormBorderStyle = FormBorderStyle.FixedDialog; + MaximizeBox = false; + MinimizeBox = false; + Name = "ResetPassword"; + StartPosition = FormStartPosition.CenterScreen; + Text = "QtC.NET Client - Reset Password"; + pEmailBox.ResumeLayout(false); + pEmailBox.PerformLayout(); + pResetPasswordBox.ResumeLayout(false); + pResetPasswordBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)pbLoginBanner).EndInit(); + ResumeLayout(false); + } + + #endregion + + private Panel pEmailBox; + private Button btnSend; + private Label lblHeader; + private TextBox tbEmail; + private Panel pResetPasswordBox; + private TextBox tbConfirmPassword; + private Label lblConfirmPassword; + private TextBox tbNewPassword; + private Label lblNewPassword; + private TextBox tbToken; + private Label lblToken; + private Button btnResetPassword; + private PictureBox pbLoginBanner; + } +} \ No newline at end of file diff --git a/qtc-net-client-2/Forms/ResetPassword.cs b/qtc-net-client-2/Forms/ResetPassword.cs new file mode 100644 index 0000000..714444f --- /dev/null +++ b/qtc-net-client-2/Forms/ResetPassword.cs @@ -0,0 +1,68 @@ +using QtCNETAPI.Services.ApiService; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace qtc_net_client_2.Forms +{ + public partial class ResetPassword : Form + { + private IApiService _apiService; + public ResetPassword(IApiService apiService) + { + _apiService = apiService; + InitializeComponent(); + } + + private async void btnSend_Click(object sender, EventArgs e) + { + if (!string.IsNullOrEmpty(tbEmail.Text)) + { + tbEmail.Enabled = false; + btnSend.Enabled = false; + + var result = await _apiService.SendPasswordResetEmail(tbEmail.Text); + if (result != null && result.Success && result.Data) + { + pEmailBox.Visible = false; + pResetPasswordBox.Visible = true; + + MessageBox.Show("Got It! You should receive an email shortly.\nIf you do not receive an email, check your spam."); + } + else + { + MessageBox.Show("Sorry, This Server Doesn't Have Email Features Enabled Or Something Went Wrong.\nIf you cannot login, you may need to contact the server admin.", "", MessageBoxButtons.OK, MessageBoxIcon.Error); + Close(); + } + } + } + + private async void btnResetPassword_Click(object sender, EventArgs e) + { + if(!string.IsNullOrEmpty(tbToken.Text) && !string.IsNullOrEmpty(tbNewPassword.Text) && !string.IsNullOrEmpty(tbConfirmPassword.Text)) + { + tbToken.Enabled = false; + tbNewPassword.Enabled = false; + tbConfirmPassword.Enabled = false; + btnResetPassword.Enabled = false; + + var result = await _apiService.ResetPassword(new QtCNETAPI.Dtos.User.UserPasswordResetDto { Token = tbToken.Text, Password = tbNewPassword.Text }); + if(result != null && result.Success && result.Data) + { + MessageBox.Show("Your Password Has Been Reset. You may now login with the new password.", "", MessageBoxButtons.OK, MessageBoxIcon.Information); + Close(); + } else + { + MessageBox.Show(result?.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error); + Close(); + } + } + } + } +} diff --git a/qtc-net-client-2/Forms/ResetPassword.resx b/qtc-net-client-2/Forms/ResetPassword.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/qtc-net-client-2/Forms/ResetPassword.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file -- 2.47.2 From cfcc5ad4c1d3c58cd6b4a91784a114bcd99a37fc Mon Sep 17 00:00:00 2001 From: Moonbase Date: Sun, 27 Jul 2025 13:54:17 -0700 Subject: [PATCH 2/2] Message Box On Register To Inform User Of Email Verification --- qtc-net-client-2/Forms/Register.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/qtc-net-client-2/Forms/Register.cs b/qtc-net-client-2/Forms/Register.cs index 270f0e0..0214548 100644 --- a/qtc-net-client-2/Forms/Register.cs +++ b/qtc-net-client-2/Forms/Register.cs @@ -43,6 +43,7 @@ namespace qtc_net_client_2.Forms if(registerResult.Success) { + MessageBox.Show("Registration Complete. If the server has email verification on, you may need to check your email for a verification link.\nIf you do not receive one, try logging in."); DialogResult = DialogResult.OK; Close(); } else -- 2.47.2