diff --git a/src/app/app.config.ts b/src/app/app.config.ts index 41f0d2c..a76e977 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -12,7 +12,6 @@ import { import { provideAngor } from '@angor'; import { TranslocoService, provideTransloco } from '@ngneat/transloco'; import { appRoutes } from 'app/app.routes'; -import { provideAuth } from 'app/core/auth/auth.provider'; import { provideIcons } from 'app/core/icons/icons.provider'; import { mockApiServices } from 'app/mock-api'; import { firstValueFrom } from 'rxjs'; @@ -81,7 +80,6 @@ export const appConfig: ApplicationConfig = { }, // Angor Configuration - provideAuth(), provideIcons(), provideAngor({ mockApi: { diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 28a9295..7e0f070 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,8 +1,7 @@ import { Route } from '@angular/router'; import { initialDataResolver } from 'app/app.resolvers'; -import { AuthGuard } from 'app/core/auth/guards/auth.guard'; -import { NoAuthGuard } from 'app/core/auth/guards/noAuth.guard'; -import { LayoutComponent } from 'app/layout/layout.component'; + import { LayoutComponent } from 'app/layout/layout.component'; +import { authGuard } from './core/auth/auth.guard'; /** * Application routes configuration @@ -13,12 +12,12 @@ export const appRoutes: Route[] = [ { path: '', pathMatch: 'full', - redirectTo: 'explore' + redirectTo: 'home' }, - // Redirect signed-in user to '/explore' + // Redirect login user to '/explore' { - path: 'signed-in-redirect', + path: 'login-redirect', pathMatch: 'full', redirectTo: 'explore' }, @@ -26,30 +25,16 @@ export const appRoutes: Route[] = [ // Routes for guests { path: '', - canActivate: [NoAuthGuard], - canActivateChild: [NoAuthGuard], component: LayoutComponent, data: { layout: 'empty' }, children: [ { - path: 'confirmation-required', - loadChildren: () => import('app/components/auth/confirmation-required/confirmation-required.routes') - }, - { - path: 'forgot-password', - loadChildren: () => import('app/components/auth/forgot-password/forgot-password.routes') - }, - { - path: 'reset-password', - loadChildren: () => import('app/components/auth/reset-password/reset-password.routes') + path: 'login', + loadChildren: () => import('app/components/auth/login/login.routes') }, { - path: 'sign-in', - loadChildren: () => import('app/components/auth/sign-in/sign-in.routes') - }, - { - path: 'sign-up', - loadChildren: () => import('app/components/auth/sign-up/sign-up.routes') + path: 'register', + loadChildren: () => import('app/components/auth/register/register.routes') } ] }, @@ -57,18 +42,14 @@ export const appRoutes: Route[] = [ // Routes for authenticated users { path: '', - canActivate: [AuthGuard], - canActivateChild: [AuthGuard], + canActivate: [authGuard], + canActivateChild: [authGuard], component: LayoutComponent, data: { layout: 'empty' }, children: [ { - path: 'sign-out', - loadChildren: () => import('app/components/auth/sign-out/sign-out.routes') - }, - { - path: 'unlock-session', - loadChildren: () => import('app/components/auth/unlock-session/unlock-session.routes') + path: 'logout', + loadChildren: () => import('app/components/auth/logout/logout.routes') } ] }, @@ -78,8 +59,8 @@ export const appRoutes: Route[] = [ // Authenticated routes for Angor { path: '', - canActivate: [AuthGuard], - canActivateChild: [AuthGuard], + canActivate: [authGuard], + canActivateChild: [authGuard], component: LayoutComponent, resolve: { initialData: initialDataResolver }, children: [ diff --git a/src/app/components/auth/confirmation-required/confirmation-required.component.html b/src/app/components/auth/confirmation-required/confirmation-required.component.html deleted file mode 100644 index 4fa6fe5..0000000 --- a/src/app/components/auth/confirmation-required/confirmation-required.component.html +++ /dev/null @@ -1,96 +0,0 @@ -
-
-
- -
- -
- - -
- Confirmation required -
-
- A confirmation mail with instructions has been sent to your - email address. Follow those instructions to confirm your email - address and activate your account. -
- - -
- Return to - sign in - -
-
-
- -
diff --git a/src/app/components/auth/confirmation-required/confirmation-required.component.ts b/src/app/components/auth/confirmation-required/confirmation-required.component.ts deleted file mode 100644 index 916de77..0000000 --- a/src/app/components/auth/confirmation-required/confirmation-required.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Component, ViewEncapsulation } from '@angular/core'; -import { RouterLink } from '@angular/router'; -import { angorAnimations } from '@angor/animations'; - -@Component({ - selector: 'auth-confirmation-required', - templateUrl: './confirmation-required.component.html', - encapsulation: ViewEncapsulation.None, - animations: angorAnimations, - standalone: true, - imports: [RouterLink], -}) -export class AuthConfirmationRequiredComponent { - /** - * Constructor - */ - constructor() {} -} diff --git a/src/app/components/auth/confirmation-required/confirmation-required.routes.ts b/src/app/components/auth/confirmation-required/confirmation-required.routes.ts deleted file mode 100644 index 495eaec..0000000 --- a/src/app/components/auth/confirmation-required/confirmation-required.routes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Routes } from '@angular/router'; -import { AuthConfirmationRequiredComponent } from 'app/components/auth/confirmation-required/confirmation-required.component'; - -export default [ - { - path: '', - component: AuthConfirmationRequiredComponent, - }, -] as Routes; diff --git a/src/app/components/auth/forgot-password/forgot-password.component.html b/src/app/components/auth/forgot-password/forgot-password.component.html deleted file mode 100644 index 5d9e289..0000000 --- a/src/app/components/auth/forgot-password/forgot-password.component.html +++ /dev/null @@ -1,147 +0,0 @@ -
-
-
- -
- -
- - -
- Forgot password? -
-
- Fill the form to reset your password -
- - - @if (showAlert) { - - {{ alert.message }} - - } - - -
- - - Email address - - @if (forgotPasswordForm.get('email').hasError('required')) { - Email address is required - } - @if (forgotPasswordForm.get('email').hasError('email')) { - - Please enter a valid email address - - } - - - - - - -
- Return to - sign in - -
-
-
-
- -
diff --git a/src/app/components/auth/forgot-password/forgot-password.component.ts b/src/app/components/auth/forgot-password/forgot-password.component.ts deleted file mode 100644 index f3dd7f2..0000000 --- a/src/app/components/auth/forgot-password/forgot-password.component.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; -import { - FormsModule, - NgForm, - ReactiveFormsModule, - UntypedFormBuilder, - UntypedFormGroup, - Validators, -} from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; -import { RouterLink } from '@angular/router'; -import { angorAnimations } from '@angor/animations'; -import { AngorAlertComponent, AngorAlertType } from '@angor/components/alert'; -import { AuthService } from 'app/core/auth/auth.service'; -import { finalize } from 'rxjs'; - -@Component({ - selector: 'auth-forgot-password', - templateUrl: './forgot-password.component.html', - encapsulation: ViewEncapsulation.None, - animations: angorAnimations, - standalone: true, - imports: [ - AngorAlertComponent, - FormsModule, - ReactiveFormsModule, - MatFormFieldModule, - MatInputModule, - MatButtonModule, - MatProgressSpinnerModule, - RouterLink, - ], -}) -export class AuthForgotPasswordComponent implements OnInit { - @ViewChild('forgotPasswordNgForm') forgotPasswordNgForm: NgForm; - - alert: { type: AngorAlertType; message: string } = { - type: 'success', - message: '', - }; - forgotPasswordForm: UntypedFormGroup; - showAlert: boolean = false; - - /** - * Constructor - */ - constructor( - private _authService: AuthService, - private _formBuilder: UntypedFormBuilder - ) {} - - // ----------------------------------------------------------------------------------------------------- - // @ Lifecycle hooks - // ----------------------------------------------------------------------------------------------------- - - /** - * On init - */ - ngOnInit(): void { - // Create the form - this.forgotPasswordForm = this._formBuilder.group({ - email: ['', [Validators.required, Validators.email]], - }); - } - - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - - /** - * Send the reset link - */ - sendResetLink(): void { - // Return if the form is invalid - if (this.forgotPasswordForm.invalid) { - return; - } - - // Disable the form - this.forgotPasswordForm.disable(); - - // Hide the alert - this.showAlert = false; - - // Forgot password - this._authService - .forgotPassword(this.forgotPasswordForm.get('email').value) - .pipe( - finalize(() => { - // Re-enable the form - this.forgotPasswordForm.enable(); - - // Reset the form - this.forgotPasswordNgForm.resetForm(); - - // Show the alert - this.showAlert = true; - }) - ) - .subscribe( - (response) => { - // Set the alert - this.alert = { - type: 'success', - message: - "Password reset sent! You'll receive an email if you are registered on our system.", - }; - }, - (response) => { - // Set the alert - this.alert = { - type: 'error', - message: - 'Email does not found! Are you sure you are already a member?', - }; - } - ); - } -} diff --git a/src/app/components/auth/forgot-password/forgot-password.routes.ts b/src/app/components/auth/forgot-password/forgot-password.routes.ts deleted file mode 100644 index 8d2e41d..0000000 --- a/src/app/components/auth/forgot-password/forgot-password.routes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Routes } from '@angular/router'; -import { AuthForgotPasswordComponent } from 'app/components/auth/forgot-password/forgot-password.component'; - -export default [ - { - path: '', - component: AuthForgotPasswordComponent, - }, -] as Routes; diff --git a/src/app/components/auth/login/login.component.html b/src/app/components/auth/login/login.component.html new file mode 100644 index 0000000..b8ec6c6 --- /dev/null +++ b/src/app/components/auth/login/login.component.html @@ -0,0 +1,75 @@ +
+
+
+ +
+ +
+ + +
+ Login +
+
+
Don't have an account?
+ Register +
+ + + Privet key test = 123
+ Public key test = 321
+
+ + + + + {{ alert.message }} + + + +
+ + + Secret Key + + + Secret Key is required + + + + + + Public Key + + + Public key is required + + + + + +
+
+
+ +
diff --git a/src/app/components/auth/login/login.component.ts b/src/app/components/auth/login/login.component.ts new file mode 100644 index 0000000..778b9d9 --- /dev/null +++ b/src/app/components/auth/login/login.component.ts @@ -0,0 +1,74 @@ +import { AngorAlertComponent } from '@angor/components/alert'; +import { CommonModule, I18nPluralPipe } from '@angular/common'; +import { Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { Router, RouterLink } from '@angular/router'; +import { SignerService } from 'app/services/signer.service'; + +@Component({ + selector: 'auth-sign-in', + templateUrl: './login.component.html', + standalone: true, + imports: [ + RouterLink, + AngorAlertComponent, + FormsModule, + ReactiveFormsModule, + MatFormFieldModule, + MatInputModule, + MatButtonModule, + MatIconModule, + MatCheckboxModule, + MatProgressSpinnerModule, + CommonModule + ], +}) +export class LoginComponent implements OnInit { + signInForm: FormGroup; + alert = { type: 'error', message: '' }; + showAlert = false; + loading = false; + + constructor( + private _formBuilder: FormBuilder, + private _router: Router, + private _signerService: SignerService + ) { } + + ngOnInit(): void { + this.signInForm = this._formBuilder.group({ + privateKey: ['', Validators.required], + publicKey: ['', Validators.required], + }); + } + + signIn(): void { + if (this.signInForm.invalid) { + return; + } + + const privateKey = this.signInForm.get('privateKey').value; + const publicKey = this.signInForm.get('publicKey').value; + + this.loading = true; + this.showAlert = false; + + // Save private and public keys in the service + this._signerService.savePrivateKeyToSession(privateKey); + this._signerService.savePublicKeyToSession(publicKey); + + if (this._signerService.getPublicKey()) { + this._router.navigateByUrl('/home'); + } else { + this.loading = false; + this.alert.message = 'Public key is missing or invalid.'; + this.showAlert = true; + } + } +} diff --git a/src/app/components/auth/login/login.routes.ts b/src/app/components/auth/login/login.routes.ts new file mode 100644 index 0000000..09ba92b --- /dev/null +++ b/src/app/components/auth/login/login.routes.ts @@ -0,0 +1,9 @@ +import { Routes } from '@angular/router'; +import { LoginComponent } from 'app/components/auth/login/login.component'; + +export default [ + { + path: '', + component: LoginComponent, + }, +] as Routes; diff --git a/src/app/components/auth/sign-out/sign-out.component.html b/src/app/components/auth/logout/logout.component.html similarity index 91% rename from src/app/components/auth/sign-out/sign-out.component.html rename to src/app/components/auth/logout/logout.component.html index 647d627..4b90ed8 100644 --- a/src/app/components/auth/sign-out/sign-out.component.html +++ b/src/app/components/auth/logout/logout.component.html @@ -12,7 +12,7 @@
- You have signed out! + You have logout!
@@ -32,8 +32,8 @@ Go to sign in + [routerLink]="['/login']" + >login
diff --git a/src/app/components/auth/sign-out/sign-out.component.ts b/src/app/components/auth/logout/logout.component.ts similarity index 75% rename from src/app/components/auth/sign-out/sign-out.component.ts rename to src/app/components/auth/logout/logout.component.ts index e465d3e..f977004 100644 --- a/src/app/components/auth/sign-out/sign-out.component.ts +++ b/src/app/components/auth/logout/logout.component.ts @@ -1,17 +1,16 @@ import { I18nPluralPipe } from '@angular/common'; import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; import { Router, RouterLink } from '@angular/router'; -import { AuthService } from 'app/core/auth/auth.service'; -import { Subject, finalize, takeUntil, takeWhile, tap, timer } from 'rxjs'; + import { Subject, finalize, takeUntil, takeWhile, tap, timer } from 'rxjs'; @Component({ - selector: 'auth-sign-out', - templateUrl: './sign-out.component.html', + selector: 'auth-logout', + templateUrl: './logout.component.html', encapsulation: ViewEncapsulation.None, standalone: true, imports: [RouterLink, I18nPluralPipe], }) -export class AuthSignOutComponent implements OnInit, OnDestroy { +export class LogoutComponent implements OnInit, OnDestroy { countdown: number = 5; countdownMapping: any = { '=1': '# second', @@ -23,8 +22,7 @@ export class AuthSignOutComponent implements OnInit, OnDestroy { * Constructor */ constructor( - private _authService: AuthService, - private _router: Router + private _router: Router ) {} // ----------------------------------------------------------------------------------------------------- @@ -36,13 +34,12 @@ export class AuthSignOutComponent implements OnInit, OnDestroy { */ ngOnInit(): void { // Sign out - this._authService.signOut(); // Redirect after the countdown timer(1000, 1000) .pipe( finalize(() => { - this._router.navigate(['sign-in']); + this._router.navigate(['login']); }), takeWhile(() => this.countdown > 0), takeUntil(this._unsubscribeAll), diff --git a/src/app/components/auth/logout/logout.routes.ts b/src/app/components/auth/logout/logout.routes.ts new file mode 100644 index 0000000..84331fb --- /dev/null +++ b/src/app/components/auth/logout/logout.routes.ts @@ -0,0 +1,9 @@ +import { Routes } from '@angular/router'; +import { LogoutComponent } from 'app/components/auth/logout/logout.component'; + +export default [ + { + path: '', + component: LogoutComponent, + }, +] as Routes; diff --git a/src/app/components/auth/sign-up/sign-up.component.html b/src/app/components/auth/register/register.component.html similarity index 97% rename from src/app/components/auth/sign-up/sign-up.component.html rename to src/app/components/auth/register/register.component.html index 4eb13ef..33f924a 100644 --- a/src/app/components/auth/sign-up/sign-up.component.html +++ b/src/app/components/auth/register/register.component.html @@ -14,14 +14,14 @@
- Sign up + Register
Already have an account?
Sign in + [routerLink]="['/login']" + >Login
@@ -140,7 +140,7 @@ (click)="signUp()" > @if (!signUpForm.disabled) { - Create your free account + Create your account } @if (signUpForm.disabled) { { - // Navigate to the confirmation required page - this._router.navigateByUrl('/confirmation-required'); - }, - (response) => { - // Re-enable the form - this.signUpForm.enable(); - // Reset the form - this.signUpNgForm.resetForm(); - - // Set the alert - this.alert = { - type: 'error', - message: 'Something went wrong, please try again.', - }; - - // Show the alert - this.showAlert = true; - } - ); } } diff --git a/src/app/components/auth/register/register.routes.ts b/src/app/components/auth/register/register.routes.ts new file mode 100644 index 0000000..1dc0fd0 --- /dev/null +++ b/src/app/components/auth/register/register.routes.ts @@ -0,0 +1,9 @@ +import { Routes } from '@angular/router'; +import { RegisterComponent } from 'app/components/auth/register/register.component'; + +export default [ + { + path: '', + component: RegisterComponent, + }, +] as Routes; diff --git a/src/app/components/auth/reset-password/reset-password.component.html b/src/app/components/auth/reset-password/reset-password.component.html deleted file mode 100644 index 8f80437..0000000 --- a/src/app/components/auth/reset-password/reset-password.component.html +++ /dev/null @@ -1,220 +0,0 @@ -
-
-
- -
- -
- - -
- Reset your password -
-
- Create a new password for your account -
- - - @if (showAlert) { - - {{ alert.message }} - - } - - -
- - - Password - - - Password is required - - - - - Password (Confirm) - - - @if ( - resetPasswordForm - .get('passwordConfirm') - .hasError('required') - ) { - - Password confirmation is required - - } - @if ( - resetPasswordForm - .get('passwordConfirm') - .hasError('mustMatch') - ) { - Passwords must match - } - - - - - - -
- Return to - sign in - -
-
-
-
- -
diff --git a/src/app/components/auth/reset-password/reset-password.component.ts b/src/app/components/auth/reset-password/reset-password.component.ts deleted file mode 100644 index 0620d27..0000000 --- a/src/app/components/auth/reset-password/reset-password.component.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; -import { - FormsModule, - NgForm, - ReactiveFormsModule, - UntypedFormBuilder, - UntypedFormGroup, - Validators, -} from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatIconModule } from '@angular/material/icon'; -import { MatInputModule } from '@angular/material/input'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; -import { RouterLink } from '@angular/router'; -import { angorAnimations } from '@angor/animations'; -import { AngorAlertComponent, AngorAlertType } from '@angor/components/alert'; -import { AngorValidators } from '@angor/validators'; -import { AuthService } from 'app/core/auth/auth.service'; -import { finalize } from 'rxjs'; - -@Component({ - selector: 'auth-reset-password', - templateUrl: './reset-password.component.html', - encapsulation: ViewEncapsulation.None, - animations: angorAnimations, - standalone: true, - imports: [ - AngorAlertComponent, - FormsModule, - ReactiveFormsModule, - MatFormFieldModule, - MatInputModule, - MatButtonModule, - MatIconModule, - MatProgressSpinnerModule, - RouterLink, - ], -}) -export class AuthResetPasswordComponent implements OnInit { - @ViewChild('resetPasswordNgForm') resetPasswordNgForm: NgForm; - - alert: { type: AngorAlertType; message: string } = { - type: 'success', - message: '', - }; - resetPasswordForm: UntypedFormGroup; - showAlert: boolean = false; - - /** - * Constructor - */ - constructor( - private _authService: AuthService, - private _formBuilder: UntypedFormBuilder - ) {} - - // ----------------------------------------------------------------------------------------------------- - // @ Lifecycle hooks - // ----------------------------------------------------------------------------------------------------- - - /** - * On init - */ - ngOnInit(): void { - // Create the form - this.resetPasswordForm = this._formBuilder.group( - { - password: ['', Validators.required], - passwordConfirm: ['', Validators.required], - }, - { - validators: AngorValidators.mustMatch( - 'password', - 'passwordConfirm' - ), - } - ); - } - - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - - /** - * Reset password - */ - resetPassword(): void { - // Return if the form is invalid - if (this.resetPasswordForm.invalid) { - return; - } - - // Disable the form - this.resetPasswordForm.disable(); - - // Hide the alert - this.showAlert = false; - - // Send the request to the server - this._authService - .resetPassword(this.resetPasswordForm.get('password').value) - .pipe( - finalize(() => { - // Re-enable the form - this.resetPasswordForm.enable(); - - // Reset the form - this.resetPasswordNgForm.resetForm(); - - // Show the alert - this.showAlert = true; - }) - ) - .subscribe( - (response) => { - // Set the alert - this.alert = { - type: 'success', - message: 'Your password has been reset.', - }; - }, - (response) => { - // Set the alert - this.alert = { - type: 'error', - message: 'Something went wrong, please try again.', - }; - } - ); - } -} diff --git a/src/app/components/auth/reset-password/reset-password.routes.ts b/src/app/components/auth/reset-password/reset-password.routes.ts deleted file mode 100644 index f1760a5..0000000 --- a/src/app/components/auth/reset-password/reset-password.routes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Routes } from '@angular/router'; -import { AuthResetPasswordComponent } from 'app/components/auth/reset-password/reset-password.component'; - -export default [ - { - path: '', - component: AuthResetPasswordComponent, - }, -] as Routes; diff --git a/src/app/components/auth/sign-in/sign-in.component.html b/src/app/components/auth/sign-in/sign-in.component.html deleted file mode 100644 index 9e4f622..0000000 --- a/src/app/components/auth/sign-in/sign-in.component.html +++ /dev/null @@ -1,178 +0,0 @@ -
-
-
- -
- -
- - -
- Sign in -
-
-
Don't have an account?
- Sign up - -
- - - @if (showAlert) { - - {{ alert.message }} - - } - - -
- - - Email address - - @if (signInForm.get('email').hasError('required')) { - Email address is required - } - @if (signInForm.get('email').hasError('email')) { - - Please enter a valid email address - - } - - - - - Password - - - Password is required - - - - - - -
-
-
Or continue with
-
-
- - -
- - - -
-
-
-
- -
diff --git a/src/app/components/auth/sign-in/sign-in.component.ts b/src/app/components/auth/sign-in/sign-in.component.ts deleted file mode 100644 index 02fbdda..0000000 --- a/src/app/components/auth/sign-in/sign-in.component.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; -import { - FormsModule, - NgForm, - ReactiveFormsModule, - UntypedFormBuilder, - UntypedFormGroup, - Validators, -} from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCheckboxModule } from '@angular/material/checkbox'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatIconModule } from '@angular/material/icon'; -import { MatInputModule } from '@angular/material/input'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; -import { ActivatedRoute, Router, RouterLink } from '@angular/router'; -import { angorAnimations } from '@angor/animations'; -import { AngorAlertComponent, AngorAlertType } from '@angor/components/alert'; -import { AuthService } from 'app/core/auth/auth.service'; - -@Component({ - selector: 'auth-sign-in', - templateUrl: './sign-in.component.html', - encapsulation: ViewEncapsulation.None, - animations: angorAnimations, - standalone: true, - imports: [ - RouterLink, - AngorAlertComponent, - FormsModule, - ReactiveFormsModule, - MatFormFieldModule, - MatInputModule, - MatButtonModule, - MatIconModule, - MatCheckboxModule, - MatProgressSpinnerModule, - ], -}) -export class AuthSignInComponent implements OnInit { - @ViewChild('signInNgForm') signInNgForm: NgForm; - - alert: { type: AngorAlertType; message: string } = { - type: 'success', - message: '', - }; - signInForm: UntypedFormGroup; - showAlert: boolean = false; - - /** - * Constructor - */ - constructor( - private _activatedRoute: ActivatedRoute, - private _authService: AuthService, - private _formBuilder: UntypedFormBuilder, - private _router: Router - ) {} - - // ----------------------------------------------------------------------------------------------------- - // @ Lifecycle hooks - // ----------------------------------------------------------------------------------------------------- - - /** - * On init - */ - ngOnInit(): void { - // Create the form - this.signInForm = this._formBuilder.group({ - email: [ - 'username@angor.io', - [Validators.required, Validators.email], - ], - password: ['admin', Validators.required], - rememberMe: [''], - }); - } - - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - - /** - * Sign in - */ - signIn(): void { - // Return if the form is invalid - if (this.signInForm.invalid) { - return; - } - - // Disable the form - this.signInForm.disable(); - - // Hide the alert - this.showAlert = false; - - // Sign in - this._authService.signIn(this.signInForm.value).subscribe( - () => { - // Set the redirect url. - // The '/signed-in-redirect' is a dummy url to catch the request and redirect the user - // to the correct page after a successful sign in. This way, that url can be set via - // routing file and we don't have to touch here. - const redirectURL = - this._activatedRoute.snapshot.queryParamMap.get( - 'redirectURL' - ) || '/signed-in-redirect'; - - // Navigate to the redirect url - this._router.navigateByUrl(redirectURL); - }, - (response) => { - // Re-enable the form - this.signInForm.enable(); - - // Reset the form - this.signInNgForm.resetForm(); - - // Set the alert - this.alert = { - type: 'error', - message: 'Wrong email or password', - }; - - // Show the alert - this.showAlert = true; - } - ); - } -} diff --git a/src/app/components/auth/sign-in/sign-in.routes.ts b/src/app/components/auth/sign-in/sign-in.routes.ts deleted file mode 100644 index 37707aa..0000000 --- a/src/app/components/auth/sign-in/sign-in.routes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Routes } from '@angular/router'; -import { AuthSignInComponent } from 'app/components/auth/sign-in/sign-in.component'; - -export default [ - { - path: '', - component: AuthSignInComponent, - }, -] as Routes; diff --git a/src/app/components/auth/sign-out/sign-out.routes.ts b/src/app/components/auth/sign-out/sign-out.routes.ts deleted file mode 100644 index e8b451b..0000000 --- a/src/app/components/auth/sign-out/sign-out.routes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Routes } from '@angular/router'; -import { AuthSignOutComponent } from 'app/components/auth/sign-out/sign-out.component'; - -export default [ - { - path: '', - component: AuthSignOutComponent, - }, -] as Routes; diff --git a/src/app/components/auth/sign-up/sign-up.routes.ts b/src/app/components/auth/sign-up/sign-up.routes.ts deleted file mode 100644 index 6b88af8..0000000 --- a/src/app/components/auth/sign-up/sign-up.routes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Routes } from '@angular/router'; -import { AuthSignUpComponent } from 'app/components/auth/sign-up/sign-up.component'; - -export default [ - { - path: '', - component: AuthSignUpComponent, - }, -] as Routes; diff --git a/src/app/components/auth/unlock-session/unlock-session.component.html b/src/app/components/auth/unlock-session/unlock-session.component.html deleted file mode 100644 index ce475cb..0000000 --- a/src/app/components/auth/unlock-session/unlock-session.component.html +++ /dev/null @@ -1,175 +0,0 @@ -
-
-
- -
- -
- - -
- Unlock your session -
-
- Your session is locked due to inactivity -
- - - @if (showAlert) { - - {{ alert.message }} - - } - - -
- - - Full name - - - - - - Password - - - Password is required - - - - - - -
- I'm not - {{ name }} -
-
-
-
- -
diff --git a/src/app/components/auth/unlock-session/unlock-session.component.ts b/src/app/components/auth/unlock-session/unlock-session.component.ts deleted file mode 100644 index a463cb3..0000000 --- a/src/app/components/auth/unlock-session/unlock-session.component.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; -import { - FormsModule, - NgForm, - ReactiveFormsModule, - UntypedFormBuilder, - UntypedFormGroup, - Validators, -} from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatIconModule } from '@angular/material/icon'; -import { MatInputModule } from '@angular/material/input'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; -import { ActivatedRoute, Router, RouterLink } from '@angular/router'; -import { angorAnimations } from '@angor/animations'; -import { AngorAlertComponent, AngorAlertType } from '@angor/components/alert'; -import { AuthService } from 'app/core/auth/auth.service'; -import { UserService } from 'app/core/user/user.service'; - -@Component({ - selector: 'auth-unlock-session', - templateUrl: './unlock-session.component.html', - encapsulation: ViewEncapsulation.None, - animations: angorAnimations, - standalone: true, - imports: [ - AngorAlertComponent, - FormsModule, - ReactiveFormsModule, - MatFormFieldModule, - MatInputModule, - MatButtonModule, - MatIconModule, - MatProgressSpinnerModule, - RouterLink, - ], -}) -export class AuthUnlockSessionComponent implements OnInit { - @ViewChild('unlockSessionNgForm') unlockSessionNgForm: NgForm; - - alert: { type: AngorAlertType; message: string } = { - type: 'success', - message: '', - }; - name: string; - showAlert: boolean = false; - unlockSessionForm: UntypedFormGroup; - private _email: string; - - /** - * Constructor - */ - constructor( - private _activatedRoute: ActivatedRoute, - private _authService: AuthService, - private _formBuilder: UntypedFormBuilder, - private _router: Router, - private _userService: UserService - ) {} - - // ----------------------------------------------------------------------------------------------------- - // @ Lifecycle hooks - // ----------------------------------------------------------------------------------------------------- - - /** - * On init - */ - ngOnInit(): void { - // Get the user's name - this._userService.user$.subscribe((user) => { - this.name = user.name; - this._email = user.email; - }); - - // Create the form - this.unlockSessionForm = this._formBuilder.group({ - name: [ - { - value: this.name, - disabled: true, - }, - ], - password: ['', Validators.required], - }); - } - - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - - /** - * Unlock - */ - unlock(): void { - // Return if the form is invalid - if (this.unlockSessionForm.invalid) { - return; - } - - // Disable the form - this.unlockSessionForm.disable(); - - // Hide the alert - this.showAlert = false; - - this._authService - .unlockSession({ - email: this._email ?? '', - password: this.unlockSessionForm.get('password').value, - }) - .subscribe( - () => { - // Set the redirect url. - // The '/signed-in-redirect' is a dummy url to catch the request and redirect the user - // to the correct page after a successful sign in. This way, that url can be set via - // routing file and we don't have to touch here. - const redirectURL = - this._activatedRoute.snapshot.queryParamMap.get( - 'redirectURL' - ) || '/signed-in-redirect'; - - // Navigate to the redirect url - this._router.navigateByUrl(redirectURL); - }, - (response) => { - // Re-enable the form - this.unlockSessionForm.enable(); - - // Reset the form - this.unlockSessionNgForm.resetForm({ - name: { - value: this.name, - disabled: true, - }, - }); - - // Set the alert - this.alert = { - type: 'error', - message: 'Invalid password', - }; - - // Show the alert - this.showAlert = true; - } - ); - } -} diff --git a/src/app/components/auth/unlock-session/unlock-session.routes.ts b/src/app/components/auth/unlock-session/unlock-session.routes.ts deleted file mode 100644 index 4fc927e..0000000 --- a/src/app/components/auth/unlock-session/unlock-session.routes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Routes } from '@angular/router'; -import { AuthUnlockSessionComponent } from 'app/components/auth/unlock-session/unlock-session.component'; - -export default [ - { - path: '', - component: AuthUnlockSessionComponent, - }, -] as Routes; diff --git a/src/app/core/auth/auth.guard.ts b/src/app/core/auth/auth.guard.ts new file mode 100644 index 0000000..1724f6d --- /dev/null +++ b/src/app/core/auth/auth.guard.ts @@ -0,0 +1,16 @@ +import { inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { SignerService } from 'app/services/signer.service'; + + +export const authGuard = () => { + const signerService = inject(SignerService); + const router = inject(Router); + + if (signerService.getPublicKey() !== "") { + return true; + } + + // Redirect to the login page + return router.parseUrl('/login'); +}; diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts deleted file mode 100644 index edfd77a..0000000 --- a/src/app/core/auth/auth.interceptor.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { - HttpErrorResponse, - HttpEvent, - HttpHandlerFn, - HttpRequest, -} from '@angular/common/http'; -import { inject } from '@angular/core'; -import { AuthService } from 'app/core/auth/auth.service'; -import { AuthUtils } from 'app/core/auth/auth.utils'; -import { Observable, catchError, throwError } from 'rxjs'; - -/** - * Intercept - * - * @param req - * @param next - */ -export const authInterceptor = ( - req: HttpRequest, - next: HttpHandlerFn -): Observable> => { - const authService = inject(AuthService); - - // Clone the request object - let newReq = req.clone(); - - // Request - // - // If the access token didn't expire, add the Authorization header. - // We won't add the Authorization header if the access token expired. - // This will force the server to return a "401 Unauthorized" response - // for the protected API routes which our response interceptor will - // catch and delete the access token from the local storage while logging - // the user out from the app. - if ( - authService.accessToken && - !AuthUtils.isTokenExpired(authService.accessToken) - ) { - newReq = req.clone({ - headers: req.headers.set( - 'Authorization', - 'Bearer ' + authService.accessToken - ), - }); - } - - // Response - return next(newReq).pipe( - catchError((error) => { - // Catch "401 Unauthorized" responses - if (error instanceof HttpErrorResponse && error.status === 401) { - // Sign out - authService.signOut(); - - // Reload the app - location.reload(); - } - - return throwError(error); - }) - ); -}; diff --git a/src/app/core/auth/auth.provider.ts b/src/app/core/auth/auth.provider.ts deleted file mode 100644 index 81beefe..0000000 --- a/src/app/core/auth/auth.provider.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { provideHttpClient, withInterceptors } from '@angular/common/http'; -import { - ENVIRONMENT_INITIALIZER, - EnvironmentProviders, - Provider, - inject, -} from '@angular/core'; -import { authInterceptor } from 'app/core/auth/auth.interceptor'; -import { AuthService } from 'app/core/auth/auth.service'; - -export const provideAuth = (): Array => { - return [ - provideHttpClient(withInterceptors([authInterceptor])), - { - provide: ENVIRONMENT_INITIALIZER, - useValue: () => inject(AuthService), - multi: true, - }, - ]; -}; diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts deleted file mode 100644 index 08c86b2..0000000 --- a/src/app/core/auth/auth.service.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { HttpClient } from '@angular/common/http'; -import { inject, Injectable } from '@angular/core'; -import { AuthUtils } from 'app/core/auth/auth.utils'; -import { UserService } from 'app/core/user/user.service'; -import { catchError, Observable, of, switchMap, throwError } from 'rxjs'; - -@Injectable({ providedIn: 'root' }) -export class AuthService { - private _authenticated: boolean = false; - private _httpClient = inject(HttpClient); - private _userService = inject(UserService); - - // ----------------------------------------------------------------------------------------------------- - // @ Accessors - // ----------------------------------------------------------------------------------------------------- - - /** - * Setter & getter for access token - */ - set accessToken(token: string) { - localStorage.setItem('accessToken', token); - } - - get accessToken(): string { - return localStorage.getItem('accessToken') ?? ''; - } - - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - - /** - * Forgot password - * - * @param email - */ - forgotPassword(email: string): Observable { - return this._httpClient.post('api/auth/forgot-password', email); - } - - /** - * Reset password - * - * @param password - */ - resetPassword(password: string): Observable { - return this._httpClient.post('api/auth/reset-password', password); - } - - /** - * Sign in - * - * @param credentials - */ - signIn(credentials: { email: string; password: string }): Observable { - // Throw error, if the user is already logged in - if (this._authenticated) { - return throwError('User is already logged in.'); - } - - return this._httpClient.post('api/auth/sign-in', credentials).pipe( - switchMap((response: any) => { - // Store the access token in the local storage - this.accessToken = response.accessToken; - - // Set the authenticated flag to true - this._authenticated = true; - - // Store the user on the user service - this._userService.user = response.user; - - // Return a new observable with the response - return of(response); - }) - ); - } - - /** - * Sign in using the access token - */ - signInUsingToken(): Observable { - // Sign in using the token - return this._httpClient - .post('api/auth/sign-in-with-token', { - accessToken: this.accessToken, - }) - .pipe( - catchError(() => - // Return false - of(false) - ), - switchMap((response: any) => { - // Replace the access token with the new one if it's available on - // the response object. - // - // This is an added optional step for better security. Once you sign - // in using the token, you should generate a new one on the server - // side and attach it to the response object. Then the following - // piece of code can replace the token with the refreshed one. - if (response.accessToken) { - this.accessToken = response.accessToken; - } - - // Set the authenticated flag to true - this._authenticated = true; - - // Store the user on the user service - this._userService.user = response.user; - - // Return true - return of(true); - }) - ); - } - - /** - * Sign out - */ - signOut(): Observable { - // Remove the access token from the local storage - localStorage.removeItem('accessToken'); - - // Set the authenticated flag to false - this._authenticated = false; - - // Return the observable - return of(true); - } - - /** - * Sign up - * - * @param user - */ - signUp(user: { - name: string; - email: string; - password: string; - company: string; - }): Observable { - return this._httpClient.post('api/auth/sign-up', user); - } - - /** - * Unlock session - * - * @param credentials - */ - unlockSession(credentials: { - email: string; - password: string; - }): Observable { - return this._httpClient.post('api/auth/unlock-session', credentials); - } - - /** - * Check the authentication status - */ - check(): Observable { - // Check if the user is logged in - if (this._authenticated) { - return of(true); - } - - // Check the access token availability - if (!this.accessToken) { - return of(false); - } - - // Check the access token expire date - if (AuthUtils.isTokenExpired(this.accessToken)) { - return of(false); - } - - // If the access token exists, and it didn't expire, sign in using it - return this.signInUsingToken(); - } -} diff --git a/src/app/core/auth/auth.utils.ts b/src/app/core/auth/auth.utils.ts deleted file mode 100644 index e5a7e3e..0000000 --- a/src/app/core/auth/auth.utils.ts +++ /dev/null @@ -1,182 +0,0 @@ -// ----------------------------------------------------------------------------------------------------- -// @ AUTH UTILITIES -// -// Methods are derivations of the Auth0 Angular-JWT helper service methods -// https://github.com/auth0/angular2-jwt -// ----------------------------------------------------------------------------------------------------- - -export class AuthUtils { - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - - /** - * Is token expired? - * - * @param token - * @param offsetSeconds - */ - static isTokenExpired(token: string, offsetSeconds?: number): boolean { - // Return if there is no token - if (!token || token === '') { - return true; - } - - // Get the expiration date - const date = this._getTokenExpirationDate(token); - - offsetSeconds = offsetSeconds || 0; - - if (date === null) { - return true; - } - - // Check if the token is expired - return !(date.valueOf() > new Date().valueOf() + offsetSeconds * 1000); - } - - // ----------------------------------------------------------------------------------------------------- - // @ Private methods - // ----------------------------------------------------------------------------------------------------- - - /** - * Base64 decoder - * Credits: https://github.com/atk - * - * @param str - * @private - */ - private static _b64decode(str: string): string { - const chars = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - let output = ''; - - str = String(str).replace(/=+$/, ''); - - if (str.length % 4 === 1) { - throw new Error( - "'atob' failed: The string to be decoded is not correctly encoded." - ); - } - - /* eslint-disable */ - for ( - // initialize result and counters - let bc = 0, bs: any, buffer: any, idx = 0; - // get next character - (buffer = str.charAt(idx++)); - // character found in table? initialize bit storage and add its ascii value; - ~buffer && - ((bs = bc % 4 ? bs * 64 + buffer : buffer), - // and if not first of each 4 characters, - // convert the first 8 bits to one ascii character - bc++ % 4) - ? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) - : 0 - ) { - // try to find character in table (0-63, not found => -1) - buffer = chars.indexOf(buffer); - } - /* eslint-enable */ - - return output; - } - - /** - * Base64 unicode decoder - * - * @param str - * @private - */ - private static _b64DecodeUnicode(str: any): string { - return decodeURIComponent( - Array.prototype.map - .call( - this._b64decode(str), - (c: any) => - '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) - ) - .join('') - ); - } - - /** - * URL Base 64 decoder - * - * @param str - * @private - */ - private static _urlBase64Decode(str: string): string { - let output = str.replace(/-/g, '+').replace(/_/g, '/'); - switch (output.length % 4) { - case 0: { - break; - } - case 2: { - output += '=='; - break; - } - case 3: { - output += '='; - break; - } - default: { - throw Error('Illegal base64url string!'); - } - } - return this._b64DecodeUnicode(output); - } - - /** - * Decode token - * - * @param token - * @private - */ - private static _decodeToken(token: string): any { - // Return if there is no token - if (!token) { - return null; - } - - // Split the token - const parts = token.split('.'); - - if (parts.length !== 3) { - throw new Error( - "The inspected token doesn't appear to be a JWT. Check to make sure it has three parts and see https://jwt.io for more." - ); - } - - // Decode the token using the Base64 decoder - const decoded = this._urlBase64Decode(parts[1]); - - if (!decoded) { - throw new Error('Cannot decode the token.'); - } - - return JSON.parse(decoded); - } - - /** - * Get token expiration date - * - * @param token - * @private - */ - private static _getTokenExpirationDate(token: string): Date | null { - // Get the decoded token - const decodedToken = this._decodeToken(token); - - // Return if the decodedToken doesn't have an 'exp' field - if (!decodedToken.hasOwnProperty('exp')) { - return null; - } - - // Convert the expiration date - const date = new Date(0); - date.setUTCSeconds(decodedToken.exp); - - return date; - } -} diff --git a/src/app/core/auth/guards/auth.guard.ts b/src/app/core/auth/guards/auth.guard.ts deleted file mode 100644 index e98780c..0000000 --- a/src/app/core/auth/guards/auth.guard.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { inject } from '@angular/core'; -import { CanActivateChildFn, CanActivateFn, Router } from '@angular/router'; -import { AuthService } from 'app/core/auth/auth.service'; -import { of, switchMap } from 'rxjs'; - -export const AuthGuard: CanActivateFn | CanActivateChildFn = (route, state) => { - const router: Router = inject(Router); - - // Check the authentication status - return inject(AuthService) - .check() - .pipe( - switchMap((authenticated) => { - // If the user is not authenticated... - if (!authenticated) { - // Redirect to the sign-in page with a redirectUrl param - const redirectURL = - state.url === '/sign-out' - ? '' - : `redirectURL=${state.url}`; - const urlTree = router.parseUrl(`sign-in?${redirectURL}`); - - return of(urlTree); - } - - // Allow the access - return of(true); - }) - ); -}; diff --git a/src/app/core/auth/guards/noAuth.guard.ts b/src/app/core/auth/guards/noAuth.guard.ts deleted file mode 100644 index 99b6af0..0000000 --- a/src/app/core/auth/guards/noAuth.guard.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { inject } from '@angular/core'; -import { CanActivateChildFn, CanActivateFn, Router } from '@angular/router'; -import { AuthService } from 'app/core/auth/auth.service'; -import { of, switchMap } from 'rxjs'; - -export const NoAuthGuard: CanActivateFn | CanActivateChildFn = ( - route, - state -) => { - const router: Router = inject(Router); - - // Check the authentication status - return inject(AuthService) - .check() - .pipe( - switchMap((authenticated) => { - // If the user is authenticated... - if (authenticated) { - return of(router.parseUrl('')); - } - - // Allow the access - return of(true); - }) - ); -}; diff --git a/src/app/core/user/user.service.ts b/src/app/core/user/user.service.ts index 90c1bd2..c46ee72 100644 --- a/src/app/core/user/user.service.ts +++ b/src/app/core/user/user.service.ts @@ -31,7 +31,7 @@ export class UserService { // ----------------------------------------------------------------------------------------------------- /** - * Get the current signed-in user data + * Get the current login user data */ get(): Observable { return this._httpClient.get('api/common/user').pipe( diff --git a/src/app/layout/common/user/user.component.ts b/src/app/layout/common/user/user.component.ts index 28f0618..d60ea16 100644 --- a/src/app/layout/common/user/user.component.ts +++ b/src/app/layout/common/user/user.component.ts @@ -59,23 +59,18 @@ export class UserComponent implements OnInit, OnDestroy { ) {} - // ----------------------------------------------------------------------------------------------------- - // @ Lifecycle hooks - // ----------------------------------------------------------------------------------------------------- - /** * On init */ ngOnInit(): void { // Subscribe to user changes - this._userService.user$ - .pipe(takeUntil(this._unsubscribeAll)) - .subscribe((user: User) => { - this.user = user; - - // Mark for check - this._changeDetectorRef.markForCheck(); - }); + this.user = { + id: '1', + name: 'Test User', + email: 'testuser@example.com', + avatar: '/images/avatars/male-06.jpg', + status: 'online' + }; this._angorConfigService.config$ .pipe(takeUntil(this._unsubscribeAll)) @@ -95,10 +90,6 @@ export class UserComponent implements OnInit, OnDestroy { this._unsubscribeAll.complete(); } - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - /** * Update the user status * @@ -123,7 +114,7 @@ export class UserComponent implements OnInit, OnDestroy { * Sign out */ signOut(): void { - this._router.navigate(['/sign-out']); + this._router.navigate(['/logout']); } /** diff --git a/src/app/services/signer.service.ts b/src/app/services/signer.service.ts index 66e4a3c..b588dcf 100644 --- a/src/app/services/signer.service.ts +++ b/src/app/services/signer.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@angular/core'; import { UnsignedEvent, nip19, getPublicKey, nip04, Event } from 'nostr-tools'; +import { Buffer } from 'buffer'; @Injectable({ @@ -38,13 +39,14 @@ export class SignerService { } nsec() { - if (this.usingPrivateKey()) { - let privateKey = this.getPrivateKey(); - const privateKeyUint8Array = Uint8Array.from(Buffer.from(privateKey, 'hex')); - return nip19.nsecEncode(privateKeyUint8Array); - } - return ""; - } + if (this.usingPrivateKey()) { + let privateKey = this.getPrivateKey(); + const privateKeyUint8Array = Uint8Array.from(Buffer.from(privateKey, 'hex')); + return nip19.nsecEncode(privateKeyUint8Array); + } + return ""; + } + pubkey(npub: string) { return nip19.decode(npub).data.toString(); @@ -123,12 +125,8 @@ export class SignerService { if (relays.length === 0 || relays[0] === "") { relays = [ "wss://relay.damus.io/", - "wss://nostr.fmt.wiz.biz/", - "wss://relay.nostr.band/", - "wss://relay.snort.social/", - "wss://nostr.mom", - "wss://relayable.org", - "wss://purplepag.es", + "wss://relay.angor.io/", + "wss://relay2.angor.io/" ] } return relays @@ -214,22 +212,28 @@ export class SignerService { } handleLoginWithNsec(nsec: string) { - let privateKey: string; - try { - privateKey = nip19.decode(nsec).data.toString(); - } catch (e) { - return false; - } + let privateKey: string; + try { + privateKey = nip19.decode(nsec).data as string; + + const privateKeyUint8Array = new Uint8Array(Buffer.from(privateKey, 'hex')); + + let pubkey = getPublicKey(privateKeyUint8Array); + + this.savePrivateKeyToSession(privateKey); + this.savePublicKeyToSession(pubkey); + + console.log("Public Key: ", this.getPublicKey()); + console.log("Private Key: ", this.getPrivateKey()); + + return true; + } catch (e) { + console.error("Error during key handling: ", e); + return false; + } + } + - // Assuming the private key is stored in hexadecimal format - const privateKeyUint8Array = Uint8Array.from(Buffer.from(privateKey, 'hex')); - let pubkey = getPublicKey(privateKeyUint8Array); - this.savePrivateKeyToSession(privateKey); - this.savePublicKeyToSession(pubkey); - console.log(this.getPublicKey()) - console.log(this.getPrivateKey()) - return true; - } usingNostrBrowserExtension() { if (this.usingPrivateKey()) { @@ -289,9 +293,19 @@ export class SignerService { } async decryptWithPrivateKey(pubkey: string, ciphertext: string): Promise { - let privateKey = this.getPrivateKey() - return await nip04.decrypt(privateKey, pubkey, ciphertext).catch((error) => { - return "*Failed to Decrypted Content*"; - }); - } + try { + // Get the stored private key in hex format + let privateKey = this.getPrivateKey(); + + // Ensure the private key is in Uint8Array format + const privateKeyUint8Array = new Uint8Array(Buffer.from(privateKey, 'hex')); + + // Decrypt the message using the private key and public key + return await nip04.decrypt(privateKeyUint8Array, pubkey, ciphertext); + } catch (error) { + console.error("Error during decryption: ", error); + return "*Failed to Decrypted Content*"; + } + } + }