Angular-ElectronJS — canActivate, interceptors, custom themes and tailwindcss

  • If you try to access the protected page, you must be redirected to another page (in this case the identification page).
  • If you are already logged in and go to the identification page, you can choose to display a message instead of the form or redirect the user to a page reserved for authenticated persons. We will opt for the second solution .
  1. The person enters his or her username and password. ✔️ (cf article)
  2. Then, clicks on the login button ✔️ (cf article)
  3. Once logged in, the user is redirected to the home page . ✔️
  4. A toolbar appears. ✔️
  5. A burger menu will display the other protected pages. ✔️
  6. We will refine the display by creating a custom theme for material.
  7. We will also add a css layer to our elements using tailwindcss
if (tokenExists) { this.router.navigate(['/']); return true; }
// redirect to home if already logged in if (this.service.currentUserValue) { this.router.navigate(['/']); }

canActivate

You have to add this property in the route definition — in the file /src/app/app-routing.module.ts

import { AuthGuard } from './providers/auth'; const routes: Routes = [ { path: '', component: HomeComponent, canActivate: [AuthGuard] }, { path: 'login', component: LoginComponent }, { path: 'event', component: EventComponent, canActivate: [AuthGuard] }, { path: 'lieux', component: LieuxComponent, canActivate: [AuthGuard] } ];
import { Injectable } from '@angular/core'; import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { LoginService } from './login.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor( private router: Router, private loginService: LoginService ) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { const currentUser = this.loginService.currentUserValue; if (currentUser) { // authorised so return true return true; } // not logged in so redirect to login page with the return url this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }}); return false; } }

… Home page

This page looks like this

logout() { this.loginService.logout(); this.router.navigate(['/login']); }

Let’s see how to display this username.

This is done in the ngOnInit method of the class HomeComponent /src/app/components/home/home.component.ts. The complete code of this class is

import { Component, OnInit } from '@angular/core'; import { first } from 'rxjs/operators'; import { User } from '../../models/user'; import { UserService } from '../../providers/user.service'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.scss'] }) export class HomeComponent implements OnInit { loading = false; users: User[]; me: User; constructor( private userService: UserService ) {} ngOnInit() { this.loading = true; this.userService.me().pipe(first()).subscribe(me => { this.loading = false; this.me = me; }); } }
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { AppConfig } from '../../environments/environment'; import { User } from '../models/user'; @Injectable({ providedIn: 'root' }) export class UserService { constructor(private http: HttpClient) { } me() { console.log(`${AppConfig.apiUrl}/user/me`); // http://localhost:3008/api/user/me return this.http.get<User>(`${AppConfig.apiUrl}/user/me`); } }
export const AppConfig = { production: false, environment: 'LOCAL', apiUrl: 'http://localhost:3008/api' };
<div class="m-8"> <div *ngIf="me"> <p>Connecté en tant que : <strong>{{ me.data.username }}</strong></p> <p class="text-center"><a routerLink="/login" [queryParams]="{logout: 1}" class="color--white">Déconnexion</a></p> </div> </div>{{ me.data.username }}

Interceptors

It’s a way to intercept or modify the global http request of an application before triggering the url called by this request.

import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { Interceptor } from './providers/interceptors/interceptor'; import { ErrorInterceptor } from './providers/interceptors/errorinterceptor';
@NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: Interceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true } ], bootstrap: [AppComponent] })
  • Pour ajouter le token Bearer dans l’entete des pages avant d’activer une page protégée.
  • Pour intercepter le code d’erreur . Cas d’une page 404 par exemple ou 401 (forbidden)

Interceptor Bearer

Créons le fichier /src/app/providers/interceptors/interceptor.ts

import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; import { LoginService } from '../login.service'; import { Observable } from 'rxjs'; @Injectable() export class Interceptor implements HttpInterceptor { constructor(private service: LoginService) {} intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler): Observable&lt;HttpEvent&lt;any&gt;&gt; { // add authorization header with jwt token if available let currentUser = this.service.currentUserValue; if (currentUser &amp;&amp; currentUser.token) { request = request.clone({ setHeaders: { Authorization: `Bearer ${currentUser.token}` } }); } return next.handle(request); } }

Burger menu on the left in the toolbar

Click on the burger

@import './assets/css/custom';
@import '~@angular/material/theming'; @include mat-core(); $custom-primary: mat-palette($mat-red); $custom-accent: mat-palette($mat-pink); $custom-theme: mat-light-theme($custom-primary, $custom-accent); @include angular-material-theme($custom-theme);
@include mat-core();
npm install tailwindcss --save-dev
npx tailwind init
@tailwind components; @tailwind utilities;
npx tailwind build ./src/tailwind-build.scss -o ./src/tailwind.scss
@import './tailwind';

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store