Skip to content

Commit

Permalink
fix issues in auth process
Browse files Browse the repository at this point in the history
  • Loading branch information
EnricoSchw committed Nov 16, 2024
1 parent 5865c84 commit bf00c6c
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 56 deletions.
9 changes: 7 additions & 2 deletions internal/auth/account/account_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func (r *AccountRepository) RedeemAccountVerificationToken(ctx context.Context,
var verificationToken VerificationToken

lastHour := time.Now().Add(-time.Hour)
result := tx.Preload("Account").Where("token = ? AND verified = ? AND created_at > ", token, false, lastHour).First(&verificationToken)
result := tx.Preload("Account").Where("uuid = ? AND verified = ? AND created_at > ?", token, false, lastHour).First(&verificationToken)
if result.Error != nil {
err := fmt.Errorf("seraching redeem account verification token %s: %w", token, result.Error)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
Expand All @@ -190,6 +190,11 @@ func (r *AccountRepository) RedeemAccountVerificationToken(ctx context.Context,
verificationToken.Verified = true
verificationToken.Account.Active = true
saved := tx.Save(&verificationToken)
if saved.Error != nil {
return fmt.Errorf("deactivate token: %s: %w", token, result.Error)
}

saved = tx.Save(verificationToken.Account)
if saved.Error != nil {
return fmt.Errorf("activating account by verification token %s: %w", token, result.Error)
}
Expand Down Expand Up @@ -224,7 +229,7 @@ func (r *AccountRepository) RedeemPassForgetToken(ctx context.Context, token str
var verificationToken VerificationToken

lastHour := time.Now().Add(-time.Hour)
result := tx.Preload("Account").Where("token = ? AND verified = ? AND created_at > ", token, false, lastHour).First(&verificationToken)
result := tx.Preload("Account").Where("uuid = ? AND verified = ? AND created_at > ?", token, false, lastHour).First(&verificationToken)
if result.Error != nil {
err := fmt.Errorf("seraching redeem pass forget token %s: %w", token, result.Error)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
Expand Down
8 changes: 5 additions & 3 deletions internal/auth/account/account_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

const activateAccountURLPath = "activateAccount"
const passwordForgetURLPath = "newPassword"
const passwordForgetURLPath = "forgotPassword"

var ErrInvalidCredentials = errors.New("invalid credentials")
var ErrAccountAlreadyExists = errors.New("account already exists")
Expand Down Expand Up @@ -104,7 +104,8 @@ func (s *AccountService) sendVerificationMail(ctx context.Context, account *Acco
return nil
}

if err := s.mailSender.SendActivateAccountMail(account.User, account.Email, link); err != nil {
username, _ := instance.SplitUserId(account.User)
if err := s.mailSender.SendActivateAccountMail(username, account.Email, link); err != nil {
return fmt.Errorf("sending verify email: %w", err)
}

Expand Down Expand Up @@ -137,7 +138,8 @@ func (s *AccountService) CreateForgotPasswordToken(ctx context.Context, email st

link := s.instanceUrl.String() + "/" + passwordForgetURLPath + "/" + token.UUID

if err := s.mailSender.SendActivateAccountMail(account.User, account.Email, link); err != nil {
username, _ := instance.SplitUserId(account.User)
if err := s.mailSender.SendForgotPasswordMail(username, account.Email, link); err != nil {
return fmt.Errorf("sending verify email for new password: %w", err)
}

Expand Down
4 changes: 2 additions & 2 deletions internal/auth/handler/forgot_password.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"golang.org/x/exp/slog"
)

func SendForgotPasswordEmail(accountService *account.AccountService) http.HandlerFunc {
func SendForgotPasswordMail(accountService *account.AccountService) http.HandlerFunc {

return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
Expand All @@ -20,7 +20,7 @@ func SendForgotPasswordEmail(accountService *account.AccountService) http.Handle
}

if err = accountService.CreateForgotPasswordToken(r.Context(), email); err != nil {
slog.Error("auth.SendForgotPasswordEmail:", "err", err)
slog.Error("auth.SendForgotPasswordMail:", "err", err)
}

w.WriteHeader(http.StatusCreated)
Expand Down
2 changes: 1 addition & 1 deletion internal/auth/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func UseRoutes(router *mux.Router, accountService *account.AccountService) {
router.HandleFunc("/authenticate", handler.Authentication(accountService)).Methods("POST")
router.HandleFunc("/auth/login", handler.Login(accountService)).Methods("POST")
router.HandleFunc("/auth/register", handler.Register(accountService)).Methods("POST")
router.HandleFunc("/auth/sendForgotPasswordEmail", handler.SendForgotPasswordEmail(accountService)).Methods("POST")
router.HandleFunc("/auth/sendForgotPasswordMail", handler.SendForgotPasswordMail(accountService)).Methods("POST")
router.HandleFunc("/auth/updateForgotPassword", handler.UpdateForgotPassword(accountService)).Methods("PUT")
router.HandleFunc("/auth/updatePassword", session.HttpMiddleware(accountService.GetConfig(), handler.UpdatePassword(accountService))).Methods("PUT")
router.HandleFunc("/auth/deleteAccount", session.HttpMiddleware(accountService.GetConfig(), handler.DeleteAccount(accountService))).Methods("POST")
Expand Down
2 changes: 1 addition & 1 deletion internal/mail/template/forgot_password.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
<tr>
<td class="wrapper" style="font-family: Helvetica, sans-serif; font-size: 16px; vertical-align: top; box-sizing: border-box; padding: 24px;" valign="top">
<div class="" style="clear: both; padding-bottom: 15px; text-align: center; width: 100%;">
<h1 style="font-family: Helvetica, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px; color: #3e3e3e;">Forgot Your Account Account</h1>
<h1 style="font-family: Helvetica, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px; color: #3e3e3e;">Forgot Password</h1>
</div>
<h3 style="font-family: Helvetica, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px; color: #3e3e3e;">Dear {{.User}}</h3>
<p style="font-family: Helvetica, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px; color: #3e3e3e;">Please click on the button below to change your password.</p>
Expand Down
31 changes: 18 additions & 13 deletions web/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,31 @@ import {UserAccessGuard} from './guards/user-access-guard.service';
import {LoginComponent} from './pages/auth/login/login.component';
import {LobbyEntryComponent} from './pages/lobby-entry/lobby-entry.component';
import {AdminAccessGuard} from './guards/admin-access-guard.service';
import {PasswordForgottenComponent} from './pages/auth/password-forgotten/password-forgotten.component';

import {SignupComponent} from './pages/auth/signup/signup.component';
import {ActivateAccountComponent} from './pages/auth/activate-account/activate-account.component';
import {ForgotPasswordComponent} from './pages/auth/forgot-password/forgot-password.component';
import {ForgotPasswordMailComponent} from './pages/auth/forgot-password-mail/forgot-password-mail.component';
import {UpdatePasswordComponent} from './pages/auth/update-password/update-password.component';

const routes: Routes = [
{path: '', redirectTo: '/dashboard', pathMatch: 'full'},
{path: 'dashboard', component: DashboardComponent, canActivate: [UserAccessGuard]},
{path: 'admin/dashboard', component: AdminDashboardComponent, canActivate: [AdminAccessGuard]},
{path: 'lobby/:spaceId/stream/:streamId', component: LobbyEntryComponent, canActivate: [UserAccessGuard]},
{path: 'login', component: LoginComponent},
{path: 'passwordForgotten', component: PasswordForgottenComponent},
{path: 'signup', component: SignupComponent},
{path: 'activateAccount/:token', component: ActivateAccountComponent}
{path: '', redirectTo: '/dashboard', pathMatch: 'full'},
{path: 'dashboard', component: DashboardComponent, canActivate: [UserAccessGuard]},
{path: 'admin/dashboard', component: AdminDashboardComponent, canActivate: [AdminAccessGuard]},
{path: 'lobby/:spaceId/stream/:streamId', component: LobbyEntryComponent, canActivate: [UserAccessGuard]},
{path: 'updatePassword', component: UpdatePasswordComponent, canActivate: [UserAccessGuard]},
{path: 'login', component: LoginComponent},
{path: 'forgotPasswordMail', component: ForgotPasswordMailComponent},
{path: 'forgotPassword/:token', component: ForgotPasswordComponent},
{path: 'signup', component: SignupComponent},
{path: 'activateAccount/:token', component: ActivateAccountComponent}
];

@NgModule({
imports: [
RouterModule.forRoot(routes)
],
exports: [RouterModule]
imports: [
RouterModule.forRoot(routes)
],
exports: [RouterModule]
})
export class AppRoutingModule {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<div>

<h1>Activate Account!</h1>
<div class="card-app">
<div class="card-title">
<h1>Activate Account!</h1>
</div>

<ng-container *ngIf="!success && !fail">
<p class="warning">We activating your Account. Please wait a Moment!</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
* {
box-sizing: border-box;
}

:host {
position: absolute;
left: 0;
right: 0;
margin-inline: auto;
width: fit-content;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,19 @@ <h1>Change Password</h1>
<input type="password" name="newPassword" placeholder="New Password" formControlName="newPassword">

<div *ngIf="passForgetForm.get('newPassword')?.invalid && (passForgetForm.get('newPassword')?.touched || passForgetForm.get('newPassword')?.dirty)" class="invalid">
<p *ngIf="passForgetForm.get('newPassword')?.errors?.['uppercaseLetter']">At least one uppercase letter.</p>
<p *ngIf="passForgetForm.get('newPassword')?.errors?.['lowercaseLetter']">At least one lowercase letter.</p>
<p *ngIf="passForgetForm.get('newPassword')?.errors?.['digit']">At least one digit.</p>
<p *ngIf="passForgetForm.get('newPassword')?.errors?.['specialCharacter']">At least one special character.</p>
<p *ngIf="passForgetForm.get('newPassword')?.errors?.['minLength']">At least 8 characters long.</p>
<p *ngIf="passForgetForm.get('newPassword')?.errors?.['uppercaseLetter']">At least one uppercase letter!</p>
<p *ngIf="passForgetForm.get('newPassword')?.errors?.['lowercaseLetter']">At least one lowercase letter!</p>
<p *ngIf="passForgetForm.get('newPassword')?.errors?.['digit']">At least one digit!</p>
<p *ngIf="passForgetForm.get('newPassword')?.errors?.['specialCharacter']">At least one special character!</p>
<p *ngIf="passForgetForm.get('newPassword')?.errors?.['minLength']">At least 8 characters long!</p>
</div>

<input type="password" name="confirmPassword" formControlName="confirmPassword">

<input type="password" name="confirmPassword" placeholder="Confirm Password" formControlName="confirmPassword">

<div *ngIf="(passForgetForm.get('confirmPassword')?.invalid && (passForgetForm.get('confirmPassword')?.dirty || passForgetForm.get('confirmPassword')?.touched) || passForgetForm.errors?.['confirm'])"
class="invalid">
<p *ngIf="passForgetForm.get('confirmPassword')?.errors?.['required']">Your original password is required!</p>
<p *ngIf="passForgetForm.errors?.['confirm']">Password does'nt match.</p>
<p *ngIf="passForgetForm.errors?.['confirm']">Password doesn't match!</p>
</div>

<button>Submit</button>
Expand Down
2 changes: 1 addition & 1 deletion web/src/app/pages/auth/login/login.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ <h1>Login</h1>
</form>

<div class="card-terms">
<span style="display: block">You forget your <a href="/password-forgotten" >Password</a>?</span>
<span style="display: block">You forget your <a href="/forgotPasswordMail" >Password</a>?</span>
</div>

</div>
18 changes: 9 additions & 9 deletions web/src/app/pages/auth/signup/signup.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ <h1>Create Account</h1>

<div *ngIf="signupForm.get('user')?.invalid && (signupForm.get('user')?.dirty || signupForm.get('user')?.touched)" class="invalid">
<p *ngIf="signupForm.get('user')?.errors?.['required']">User name is required!</p>
<p *ngIf="signupForm.get('user')?.errors?.['min']">User name must be at least 4 characters long.!</p>
<p *ngIf="signupForm.get('user')?.errors?.['min']">User name must be at least 4 characters long!</p>
</div>

<input type="email" name="email" placeholder="Email" formControlName="email">
Expand All @@ -25,19 +25,19 @@ <h1>Create Account</h1>
<input type="password" name="password" placeholder="Password" formControlName="password">

<div *ngIf="signupForm.get('password')?.invalid && (signupForm.get('password')?.touched || signupForm.get('password')?.dirty)" class="invalid">
<p *ngIf="signupForm.get('password')?.errors?.['uppercaseLetter']">At least one uppercase letter.</p>
<p *ngIf="signupForm.get('password')?.errors?.['lowercaseLetter']">At least one lowercase letter.</p>
<p *ngIf="signupForm.get('password')?.errors?.['digit']">At least one digit.</p>
<p *ngIf="signupForm.get('password')?.errors?.['specialCharacter']">At least one special character.</p>
<p *ngIf="signupForm.get('password')?.errors?.['minLength']">At least 8 characters long.</p>
<p *ngIf="signupForm.get('password')?.errors?.['uppercaseLetter']">At least one uppercase letter!</p>
<p *ngIf="signupForm.get('password')?.errors?.['lowercaseLetter']">At least one lowercase letter!</p>
<p *ngIf="signupForm.get('password')?.errors?.['digit']">At least one digit!</p>
<p *ngIf="signupForm.get('password')?.errors?.['specialCharacter']">At least one special character!</p>
<p *ngIf="signupForm.get('password')?.errors?.['minLength']">At least 8 characters long!</p>
</div>

<input type="password" name="confirmPassword" formControlName="confirmPassword">
<input type="password" name="confirmPassword" placeholder="Confirm Password" formControlName="confirmPassword">

<div *ngIf="(signupForm.get('confirmPassword')?.invalid && (signupForm.get('confirmPassword')?.dirty || signupForm.get('confirmPassword')?.touched) || passForgetForm.errors?.['confirm'])"
<div *ngIf="(signupForm.get('confirmPassword')?.invalid && (signupForm.get('confirmPassword')?.dirty || signupForm.get('confirmPassword')?.touched) || signupForm.errors?.['confirm'])"
class="invalid">
<p *ngIf="signupForm.get('confirmPassword')?.errors?.['required']">Your original password is required!</p>
<p *ngIf="signupForm.errors?.['confirm']">Password does'nt match.</p>
<p *ngIf="signupForm.errors?.['confirm']">Password doesn't match!</p>
</div>


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,20 @@ <h1>Change Password</h1>
<div
*ngIf="updateForm.get('newPassword')?.invalid && (updateForm.get('newPassword')?.touched || updateForm.get('newPassword')?.dirty)"
class="invalid">
<p *ngIf="updateForm.get('newPassword')?.errors?.['uppercaseLetter']">At least one uppercase letter.</p>
<p *ngIf="updateForm.get('newPassword')?.errors?.['lowercaseLetter']">At least one lowercase letter.</p>
<p *ngIf="updateForm.get('newPassword')?.errors?.['digit']">At least one digit.</p>
<p *ngIf="updateForm.get('newPassword')?.errors?.['specialCharacter']">At least one special character.</p>
<p *ngIf="updateForm.get('newPassword')?.errors?.['minLength']">At least 8 characters long.</p>
<p *ngIf="updateForm.get('newPassword')?.errors?.['uppercaseLetter']">At least one uppercase letter!</p>
<p *ngIf="updateForm.get('newPassword')?.errors?.['lowercaseLetter']">At least one lowercase letter!</p>
<p *ngIf="updateForm.get('newPassword')?.errors?.['digit']">At least one digit!</p>
<p *ngIf="updateForm.get('newPassword')?.errors?.['specialCharacter']">At least one special character!</p>
<p *ngIf="updateForm.get('newPassword')?.errors?.['minLength']">At least 8 characters long!</p>
</div>

<input type="password" name="confirmPassword" formControlName="confirmPassword">
<input type="password" name="confirmPassword" laceholder="Confirm Password" formControlName="confirmPassword">

<div
*ngIf="(updateForm.get('confirmPassword')?.invalid && (updateForm.get('confirmPassword')?.dirty || updateForm.get('confirmPassword')?.touched) || updateForm.errors?.['confirm'])"
class="invalid">
<p *ngIf="updateForm.get('confirmPassword')?.errors?.['required']">Your original password is required!</p>
<p *ngIf="updateForm.errors?.['confirm']">Password does'nt match.</p>
<p *ngIf="updateForm.errors?.['confirm']">Password doesn't match!</p>
</div>

<button>Submit</button>
Expand Down
12 changes: 6 additions & 6 deletions web/src/app/validators/password.validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const PASSWORD_CONSTRAIN: RegExp = /^(?=[^A-Z]*[A-Z])(?=[^a-z]*[a-z])(?=\
const UPPERCASE_LETTER_CONSTRAIN: RegExp = /^(?=.*[A-Z])/;
const LOWERCASE_LETTER_CONSTRAIN: RegExp = /(?=.*[a-z])/;
const DIGIT_CONSTRAIN: RegExp = /(.*[0-9].*)/;
const SPECIAL_CHARACTER_CONSTRAIN: RegExp = /^(?=.*[!@#$%^&*])/;
const SPECIAL_CHARACTER_CONSTRAIN: RegExp = /^(?=.*[!@#$%^&*/-_:;+`´,'"(){}|?])/;
const MIN_LENGTH_CONSTRAIN: RegExp = /.{8,}/;

export class PasswordValidator {
Expand All @@ -17,22 +17,22 @@ export class PasswordValidator {
}

public static uppercaseLetter(control: AbstractControl): ValidationErrors | null {
return !control?.value?.match(UPPERCASE_LETTER_CONSTRAIN) ? null : {uppercaseLetter: true};
return control?.value?.match(UPPERCASE_LETTER_CONSTRAIN) ? null : {uppercaseLetter: true};
}

public static lowercaseLetter(control: AbstractControl): ValidationErrors | null {
return !control?.value?.match(LOWERCASE_LETTER_CONSTRAIN) ? null : {lowercaseLetter: true};
return control?.value?.match(LOWERCASE_LETTER_CONSTRAIN) ? null : {lowercaseLetter: true};
}

public static digit(control: AbstractControl): ValidationErrors | null {
return !control?.value?.match(DIGIT_CONSTRAIN) ? null : {digit: true};
return control?.value?.match(DIGIT_CONSTRAIN) ? null : {digit: true};
}

public static specialCharacter(control: AbstractControl): ValidationErrors | null {
return !control?.value?.match(SPECIAL_CHARACTER_CONSTRAIN) ? null : {specialCharacter: true};
return control?.value?.match(SPECIAL_CHARACTER_CONSTRAIN) ? null : {specialCharacter: true};
}

public static minLength(control: AbstractControl): ValidationErrors | null {
return !control?.value?.match(MIN_LENGTH_CONSTRAIN) ? null : {minLength: true};
return control?.value?.match(MIN_LENGTH_CONSTRAIN) ? null : {minLength: true};
}
}

0 comments on commit bf00c6c

Please sign in to comment.