Autentifikácia v Ionic (ver.5) aplikácii cez REST API (3.časť) - prihlasovanie
Tags: ionic, laravel, mysql
Published: 2022-09-23 16:59:28

V [prvej časti](https://dev.to/jurajchovan/autentifikacia-v-ionic-ver5-aplikacii-cez-rest-api-1cast-2n6d) sú informácie o tom, aké sú REST API volania a čo (v prípade úspechu) vracajú.
V [druhej časti](https://dev.to/jurajchovan/autentifikacia-v-ionic-ver5-aplikacii-cez-rest-api-2cast-15j3) je postup ako vytvoreniť funkcionalitu "Registrácia" v Ionic (ver.5) aplikácii.

V tejto časti si vytvorím funkcionalitu "Prihlásenie".
V servise "auth" (tj.v súbore "../services/auth.service.ts") už mám definovanú funkciu "login", cez ktorú sa obraciam na požadované REST API rozhranie:
```
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { User } from '../models/user';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  private url = 'http://127.0.0.1:8000/api';

  constructor(
    private http: HttpClient
  ) { }

  // registracia noveho pouzivatela:
  register(user: User) {
    return this.http.post(`${this.url}/register`, user);
  }
  // login existujuceho pouzivatela:
  login(credentials: User): Observable<string> {
    return this.http.post<{access_token: string}>(`${this.url}/login`, credentials).pipe(
      map(response => response.access_token)
    );
  }
}
```
Teraz si upravím kód pre stránku "Login" - do súboru layout-u stránky "login.page.html" si pridám kód:

```
<ion-header>
  <ion-toolbar>
    <ion-title>Login</ion-title>
    <ion-buttons slot="start">
      <ion-back-button defaultHref="home"></ion-back-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
  <form [formGroup]="form" (submit)="onSubmit()">
    <ion-item>
      <ion-label position="floating">Email:</ion-label>
      <ion-input type="text" required formControlName="email"></ion-input>
    </ion-item>
    <ion-item>
      <ion-label position="floating">Password:</ion-label>
      <ion-input type="password" required formControlName="password"></ion-input>
    </ion-item>
    <ion-button type="submit" class="ion-margin-top" expand="block" [disabled]="form.invalid">Login</ion-button>
  </form>
</ion-content>
```
V súbore logiky stránky "login.page.ts" pridám tento kód:

```
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { AlertController, LoadingController, ToastController } from '@ionic/angular';
import { AuthService } from 'src/app/services/auth.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss'],
})
export class LoginPage {

  constructor(
    private authService: AuthService,
    private alertCtrl: AlertController,
    private toastCtrl: ToastController,
    private loadingCtrl: LoadingController,
    private router: Router,
  ) { }

  form = new FormGroup({
    email: new FormControl('', [Validators.required, Validators.minLength(6)]),
    password: new FormControl('', [Validators.required, Validators.minLength(3)]),
  });

  // odosle logovaci formular s udajmi (pre prihlasenie existujuceho pouzivatela):
  async onSubmit() {
    console.log(this.form.value);
    const loading = await this.loadingCtrl.create({
      message: 'Logging ...'
    });
    await loading.present();
    this.authService.login(this.form.value).subscribe(
      // ak je uspesny login:
      async access_token => {
        localStorage.setItem('token', access_token);
        console.log('token: '+access_token);
        loading.dismiss();
        this.router.navigateByUrl('/home');
      },
      // ak sa vyskytla nejaka chyba:
      async () => {
        const alert = await this.alertCtrl.create({
          message: 'Login failed',
          buttons: ['OK']
        });
        await alert.present();
        loading.dismiss();
        this.form.reset();
      }
    );
  }

}

```
a ešte je potrebné upraviť kód aj v súbore "login.module.ts":

```
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { IonicModule } from '@ionic/angular';

import { LoginPageRoutingModule } from './login-routing.module';

import { LoginPage } from './login.page';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    IonicModule,
    LoginPageRoutingModule
  ],
  declarations: [LoginPage]
})
export class LoginPageModule {}
```
kde som pridal "ReactiveFormsModule".
V súbore "app.module.ts" sú už veci doplnené (viď [druhá časť](https://dev.to/jurajchovan/autentifikacia-v-ionic-ver5-aplikacii-cez-rest-api-2cast-15j3)).
Ak si dám teraz zobraziť stránku "login", tj.URL:
```
http://localhost:8100/login
```
zobrazí sa prihlasovací formulár:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/egg773ts3m8o1j6rktof.PNG)


## Otestovanie funkcionality "Prihlásenie"
Ako už bolo spomenuté v [druhej časti](https://dev.to/jurajchovan/autentifikacia-v-ionic-ver5-aplikacii-cez-rest-api-2cast-15j3) je potrebné mať štartnutý MySQL databázový server, a tiež musí bežať backend-ová aplikácia, ktorá pokrýva REST API rozhranie (v mojom prípade je to aplikácia písaná v Laravel framework-u).
Ak to beží, môžem vyskúšať cez REST klienta (napr.utilitu "Insomnia" alebo "Postman") či v [prvej časti](https://dev.to/jurajchovan/autentifikacia-v-ionic-ver5-aplikacii-cez-rest-api-1cast-2n6d) uvádzané request-y fungujú (tj.odpovedajú):

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w8ieoi0qznmep9vrufne.PNG)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mlmugyof0eimnm4b3deh.PNG)
čo znamená, že REST API rozhranie "žije" a funguje. 

Teraz si odskúšam samotnú Ionic aplikáciu - spustiť (v adresári Ionic projektu) developovací server, príkazom:
```
ionic serve
```
v prehliadači si zobraziť Ionic aplikáciu, tj.URL:
```
http://localhost:8100/home
```
čo zobrazí:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/md07j7e9yy0y6bhdifvp.PNG)
Prejsť na stránku "Login", kde vyplniť potrebné informácie k prihláseniu sa existujúceho používateľa:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0o0o4rf0kuf9wdvj5jgn.PNG)
prihlásiť sa cez [Login] a:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/brw68u4gbwvjc949mfpj.PNG)
keďže vrátilo "token", znamená to, že prihlásenie bolo úspešné a REST API request zafungoval aj z tejto Ionic aplikácie.
Po úspešnom prihlásení je presmerovanie na stránku "Home", tak ako je to vydefinované v súbore stránky "login.page.ts".

Ešte upravím domovskú stránku "Home" tak, aby v prípade úspešného prihlásenia bolo na nej tlačítko [Logout], a v prípade, že používateľ nie je prihlásený, bude tam mať dvojicu [Register] a [Login].
V súbore layout-u stránky "Home" (v súbore "../app/home/home.page.html") upravím kód takto:

```
<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>
      Blank
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <ion-header collapse="condense">
    <ion-toolbar>
      <ion-title size="large">Blank</ion-title>
    </ion-toolbar>
  </ion-header>

  <div id="container">
    <div *ngIf="loggedUser; else noLoggedUser">
      <strong>Moja Ionic app</strong>
      <div class="button-container">
        <ion-button >Logout</ion-button>
      </div>
    </div>
    <ng-template #noLoggedUser>
      <strong>Moja Ionic app</strong>
      <div class="button-container">
        <ion-button (click)="goToRegisterPage()">Register</ion-button>
        <ion-button (click)="goToLoginPage()">Login</ion-button>
      </div>
    </ng-template>
  </div>
  
</ion-content>
```
A v súbore "../app/home/home.page.ts" zase doplním zistenie, či "localStorage" obsahuje hodnotu nejakého tokenu:

```
import { Component } from '@angular/core';
import {NavController} from '@ionic/angular';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  loggedUser = localStorage.getItem('token');

  constructor(
    private navCtrl: NavController
  ) {}

  goToLoginPage() {
    this.navCtrl.navigateForward('login');
  }
  goToRegisterPage() {
    this.navCtrl.navigateForward('register');
  }
}
```
Ak sa teraz prihlásim do aplikácie, po prihlásení ma presmeruje na domovskú stránku "Home", kde bude už tlačítko [Logout]:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h2exvt9fpul0n6ez6tbo.PNG)
...