Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions src/app/app.component.ts

This file was deleted.

14 changes: 7 additions & 7 deletions src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { JwtService } from './core/auth/services/jwt.service';
import { UserService } from './core/auth/services/user.service';
import { apiInterceptor } from './core/interceptors/api.interceptor';
import { tokenInterceptor } from './core/interceptors/token.interceptor';
import { errorInterceptor } from './core/interceptors/error.interceptor';
import { Jwt } from './core/auth/services/jwt';
import { UserAuth } from './core/auth/services/user-auth';
import { apiInterceptor } from './core/interceptors/api-interceptor';
import { tokenInterceptor } from './core/interceptors/token-interceptor';
import { errorInterceptor } from './core/interceptors/error-interceptor';
import { EMPTY } from 'rxjs';

export function initAuth(jwtService: JwtService, userService: UserService) {
export function initAuth(jwtService: Jwt, userService: UserAuth) {
return () => (jwtService.getToken() ? userService.getCurrentUser() : EMPTY);
}

Expand All @@ -20,7 +20,7 @@ export const appConfig: ApplicationConfig = {
provideRouter(routes),
provideHttpClient(withInterceptors([apiInterceptor, tokenInterceptor, errorInterceptor])),
provideAppInitializer(() => {
const initializerFn = initAuth(inject(JwtService), inject(UserService));
const initializerFn = initAuth(inject(Jwt), inject(UserAuth));
return initializerFn();
}),
],
Expand Down
File renamed without changes.
28 changes: 14 additions & 14 deletions src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
import { Routes } from '@angular/router';
import { inject } from '@angular/core';
import { UserService } from './core/auth/services/user.service';
import { UserAuth } from './core/auth/services/user-auth';
import { map } from 'rxjs/operators';

export const routes: Routes = [
{
path: '',
loadComponent: () => import('./features/article/pages/home/home.component'),
loadComponent: () => import('./features/article/pages/home/home'),
},
{
path: 'tag/:tag',
loadComponent: () => import('./features/article/pages/home/home.component'),
loadComponent: () => import('./features/article/pages/home/home'),
},
{
path: 'login',
loadComponent: () => import('./core/auth/auth.component'),
canActivate: [() => inject(UserService).isAuthenticated.pipe(map(isAuth => !isAuth))],
loadComponent: () => import('./core/auth/auth'),
canActivate: [() => inject(UserAuth).isAuthenticated.pipe(map(isAuth => !isAuth))],
},
{
path: 'register',
loadComponent: () => import('./core/auth/auth.component'),
canActivate: [() => inject(UserService).isAuthenticated.pipe(map(isAuth => !isAuth))],
loadComponent: () => import('./core/auth/auth'),
canActivate: [() => inject(UserAuth).isAuthenticated.pipe(map(isAuth => !isAuth))],
},
{
path: 'settings',
loadComponent: () => import('./features/settings/settings.component'),
canActivate: [() => inject(UserService).isAuthenticated],
loadComponent: () => import('./features/settings/settings'),
canActivate: [() => inject(UserAuth).isAuthenticated],
},
{
path: 'profile',
Expand All @@ -36,18 +36,18 @@ export const routes: Routes = [
children: [
{
path: '',
loadComponent: () => import('./features/article/pages/editor/editor.component'),
canActivate: [() => inject(UserService).isAuthenticated],
loadComponent: () => import('./features/article/pages/editor/editor'),
canActivate: [() => inject(UserAuth).isAuthenticated],
},
{
path: ':slug',
loadComponent: () => import('./features/article/pages/editor/editor.component'),
canActivate: [() => inject(UserService).isAuthenticated],
loadComponent: () => import('./features/article/pages/editor/editor'),
canActivate: [() => inject(UserAuth).isAuthenticated],
},
],
},
{
path: 'article/:slug',
loadComponent: () => import('./features/article/pages/article/article.component'),
loadComponent: () => import('./features/article/pages/article/article'),
},
];
12 changes: 12 additions & 0 deletions src/app/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Header } from './core/layout/header';
import { RouterOutlet } from '@angular/router';
import { Footer } from './core/layout/footer';

@Component({
selector: 'app-root',
templateUrl: './app.html',
imports: [Header, RouterOutlet, Footer],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ChangeDetectionStrategy, Component, DestroyRef, inject, OnInit, signal } from '@angular/core';
import { Validators, FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { ListErrorsComponent } from '../../shared/components/list-errors.component';
import { ListErrors } from '../../shared/components/list-errors';
import { Errors } from '../models/errors.model';
import { UserService } from './services/user.service';
import { UserAuth } from './services/user-auth';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

interface AuthForm {
Expand All @@ -14,11 +14,11 @@ interface AuthForm {

@Component({
selector: 'app-auth-page',
templateUrl: './auth.component.html',
imports: [RouterLink, ListErrorsComponent, ReactiveFormsModule],
templateUrl: './auth.html',
imports: [RouterLink, ListErrors, ReactiveFormsModule],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export default class AuthComponent implements OnInit {
export default class Auth implements OnInit {
authType = '';
title = '';
errors = signal<Errors>({ errors: {} });
Expand All @@ -29,7 +29,7 @@ export default class AuthComponent implements OnInit {
constructor(
private readonly route: ActivatedRoute,
private readonly router: Router,
private readonly userService: UserService,
private readonly userService: UserAuth,
) {
this.authForm = new FormGroup<AuthForm>({
email: new FormControl('', {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { DestroyRef, Directive, inject, Input, OnInit, signal, TemplateRef, ViewContainerRef } from '@angular/core';
import { UserService } from './services/user.service';
import { UserAuth } from './services/user-auth';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

@Directive({
selector: '[ifAuthenticated]',
standalone: true,
})
export class IfAuthenticatedDirective<T> implements OnInit {
export class IfAuthenticated<T> implements OnInit {
destroyRef = inject(DestroyRef);
constructor(
private templateRef: TemplateRef<T>,
private userService: UserService,
private userService: UserAuth,
private viewContainer: ViewContainerRef,
) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import 'zone.js/testing';
import { describe, it, expect, beforeEach, afterEach, beforeAll, vi } from 'vitest';
import { TestBed, getTestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
import { JwtService } from './jwt.service';
import { Jwt } from './jwt';

describe('JwtService', () => {
let service: JwtService;
describe('Jwt', () => {
let service: Jwt;
let localStorageSpy: any;

beforeAll(() => {
Expand All @@ -30,10 +30,10 @@ describe('JwtService', () => {
});

TestBed.configureTestingModule({
providers: [JwtService],
providers: [Jwt],
});

service = TestBed.inject(JwtService);
service = TestBed.inject(Jwt);
});

afterEach(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class JwtService {
export class Jwt {
getToken(): string {
return window.localStorage['jwtToken'];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@ang
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Router } from '@angular/router';
import { firstValueFrom } from 'rxjs';
import { UserService } from './user.service';
import { JwtService } from './jwt.service';
import { UserAuth } from './user-auth';
import { Jwt } from './jwt';
import { User } from '../user.model';

describe('UserService', () => {
describe('UserAuth', () => {
beforeAll(() => {
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
});

let service: UserService;
let service: UserAuth;
let httpMock: HttpTestingController;
let jwtService: any;
let router: any;
Expand All @@ -40,10 +40,10 @@ describe('UserService', () => {

TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [UserService, { provide: JwtService, useValue: jwtService }, { provide: Router, useValue: router }],
providers: [UserAuth, { provide: Jwt, useValue: jwtService }, { provide: Router, useValue: router }],
});

service = TestBed.inject(UserService);
service = TestBed.inject(UserAuth);
httpMock = TestBed.inject(HttpTestingController);
});

Expand Down Expand Up @@ -286,7 +286,7 @@ describe('UserService', () => {
});

describe('setAuth', () => {
it('should save token to JwtService', () => {
it('should save token to Jwt', () => {
service.setAuth(mockUser);
expect(jwtService.saveToken).toHaveBeenCalledWith(mockUser.token);
});
Expand All @@ -305,7 +305,7 @@ describe('UserService', () => {
});

describe('purgeAuth', () => {
it('should destroy token in JwtService', () => {
it('should destroy token in Jwt', () => {
service.purgeAuth();
expect(jwtService.destroyToken).toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';

import { JwtService } from './jwt.service';
import { Jwt } from './jwt';
import { map, distinctUntilChanged, tap, shareReplay } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';
import { User } from '../user.model';
import { Router } from '@angular/router';

@Injectable({ providedIn: 'root' })
export class UserService {
export class UserAuth {
private currentUserSubject = new BehaviorSubject<User | null>(null);
public currentUser = this.currentUserSubject.asObservable().pipe(distinctUntilChanged());

public isAuthenticated = this.currentUser.pipe(map(user => !!user));

constructor(
private readonly http: HttpClient,
private readonly jwtService: JwtService,
private readonly jwtService: Jwt,
private readonly router: Router,
) {}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { inject } from '@angular/core';
import { HttpInterceptorFn } from '@angular/common/http';
import { JwtService } from '../auth/services/jwt.service';
import { Jwt } from '../auth/services/jwt';

export const tokenInterceptor: HttpInterceptorFn = (req, next) => {
const token = inject(JwtService).getToken();
const token = inject(Jwt).getToken();

const request = req.clone({
setHeaders: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { RouterLink } from '@angular/router';

@Component({
selector: 'app-layout-footer',
templateUrl: './footer.component.html',
templateUrl: './footer.html',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [DatePipe, RouterLink],
})
export class FooterComponent {
export class Footer {
today: number = Date.now();
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { UserService } from '../auth/services/user.service';
import { UserAuth } from '../auth/services/user-auth';
import { RouterLink, RouterLinkActive } from '@angular/router';
import { AsyncPipe } from '@angular/common';
import { IfAuthenticatedDirective } from '../auth/if-authenticated.directive';
import { IfAuthenticated } from '../auth/if-authenticated';

@Component({
selector: 'app-layout-header',
templateUrl: './header.component.html',
imports: [RouterLinkActive, RouterLink, AsyncPipe, IfAuthenticatedDirective],
templateUrl: './header.html',
imports: [RouterLinkActive, RouterLink, AsyncPipe, IfAuthenticated],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HeaderComponent {
currentUser$ = inject(UserService).currentUser;
export class Header {
currentUser$ = inject(UserAuth).currentUser;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, inject } from '@angular/core';
import { UserService } from '../../../core/auth/services/user.service';
import { UserAuth } from '../../../core/auth/services/user-auth';
import { User } from '../../../core/auth/user.model';
import { RouterLink } from '@angular/router';
import { map } from 'rxjs/operators';
Expand Down Expand Up @@ -39,11 +39,11 @@ import { AsyncPipe, DatePipe } from '@angular/common';
imports: [RouterLink, DatePipe, AsyncPipe],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ArticleCommentComponent {
export class ArticleComment {
@Input() comment!: Comment;
@Output() delete = new EventEmitter<boolean>();

canModify$ = inject(UserService).currentUser.pipe(
canModify$ = inject(UserAuth).currentUser.pipe(
map((userData: User | null) => userData?.username === this.comment.author.username),
);
}
Loading