Skip to content
Prev Previous commit
Next Next commit
added auth service and auth store
  • Loading branch information
rnastyuk committed Mar 3, 2025
commit 01776c39b10fbc3f0d84a6f47b44c61ca3d2a44d
8 changes: 8 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { NgModule } from '@angular/core';
import { NgxsModule } from '@ngxs/store';
import { AuthState } from '@core/store/auth';

@NgModule({
imports: [NgxsModule.forRoot([AuthState])],
})
export class AppModule {}
9 changes: 9 additions & 0 deletions src/app/core/store/auth/auth.actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export class SetAuthToken {
static readonly type = '[Auth] Set Auth Token';

constructor(public accessToken: string) {}
}

export class ClearAuth {
static readonly type = '[Auth] Clear Auth';
}
4 changes: 4 additions & 0 deletions src/app/core/store/auth/auth.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface AuthStateModel {
accessToken: string | null;
isAuthenticated: boolean;
}
15 changes: 15 additions & 0 deletions src/app/core/store/auth/auth.selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Selector } from '@ngxs/store';
import { AuthState } from './auth.state';
import { AuthStateModel } from './auth.model';

export class AuthSelectors {
@Selector([AuthState])
static isAuthenticated(state: AuthStateModel): boolean {
return state.isAuthenticated;
}

@Selector([AuthState])
static getAuthToken(state: AuthStateModel): string | null {
return state.accessToken;
}
}
30 changes: 30 additions & 0 deletions src/app/core/store/auth/auth.state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { AuthStateModel } from './auth.model';
import { SetAuthToken, ClearAuth } from './auth.actions';

@State<AuthStateModel>({
name: 'auth',
defaults: {
accessToken: null,
isAuthenticated: false,
},
})
@Injectable()
export class AuthState {
@Action(SetAuthToken)
setAuthToken(ctx: StateContext<AuthStateModel>, action: SetAuthToken) {
ctx.patchState({
accessToken: action.accessToken,
isAuthenticated: true,
});
}

@Action(ClearAuth)
clearAuth(ctx: StateContext<AuthStateModel>) {
ctx.patchState({
accessToken: null,
isAuthenticated: false,
});
}
}
4 changes: 4 additions & 0 deletions src/app/core/store/auth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './auth.actions';
export * from './auth.model';
export * from './auth.selectors';
export * from './auth.state';
8 changes: 8 additions & 0 deletions src/app/features/auth/auth.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface LoginCredentials {
email: string;
password: string;
}

export interface AuthResponse {
accessToken: string;
}
53 changes: 53 additions & 0 deletions src/app/features/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Store } from '@ngxs/store';
import { firstValueFrom } from 'rxjs';
import { LoginCredentials, AuthResponse } from './auth.entity';
import { SetAuthToken, ClearAuth } from '@core/store/auth';

@Injectable({
providedIn: 'root',
})
export class AuthService {
private readonly API_URL: string = 'VALID_API_URL';
private readonly AUTH_TOKEN_KEY: string = '';

private readonly http: HttpClient = inject(HttpClient);
private readonly store: Store = inject(Store);

async login(credentials: LoginCredentials): Promise<void> {
try {
const response: AuthResponse = await firstValueFrom(
this.http.post<AuthResponse>(`${this.API_URL}/auth/login`, credentials),
);

if (response.accessToken) {
this.setAuthToken(response.accessToken);
this.store.dispatch(new SetAuthToken(response.accessToken));
}
} catch (error) {
console.error('Login failed:', error);
throw error;
}
}

logout(): void {
localStorage.removeItem(this.AUTH_TOKEN_KEY);
this.store.dispatch(new ClearAuth());
}

getAuthToken(): string | null {
return localStorage.getItem(this.AUTH_TOKEN_KEY);
}

private setAuthToken(token: string): void {
localStorage.setItem(this.AUTH_TOKEN_KEY, token);
}

private checkInitialAuthState(): void {
const token: string | null = this.getAuthToken();
if (token) {
this.store.dispatch(new SetAuthToken(token));
}
}
}