[go: nahoru, domu]

Skip to content

Commit

Permalink
feat: authentication system
Browse files Browse the repository at this point in the history
added a dual-purpose login/register page and guarded JournalPage from unauthenticated Users.
included menu with logout button.
  • Loading branch information
momargoh committed Feb 6, 2023
1 parent 9477018 commit 0764094
Show file tree
Hide file tree
Showing 12 changed files with 292 additions and 8 deletions.
9 changes: 9 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
import { canActivate, redirectUnauthorizedTo } from '@angular/fire/auth-guard';

const redirectUnauthorized = () => redirectUnauthorizedTo(['login']);

const routes: Routes = [
{
path: 'journal',
loadChildren: () =>
import('./journal/journal.module').then((m) => m.JournalPageModule),
...canActivate(redirectUnauthorized),
},
{
path: 'login',
loadChildren: () =>
import('./auth/login/login.module').then((m) => m.LoginPageModule),
},
{
path: '',
Expand Down
29 changes: 23 additions & 6 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,33 @@ import { IonicModule, IonicRouteStrategy } from '@ionic/angular';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { initializeApp,provideFirebaseApp } from '@angular/fire/app';
import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { environment } from '../environments/environment';
import { provideAnalytics,getAnalytics,ScreenTrackingService,UserTrackingService } from '@angular/fire/analytics';
import { provideAuth,getAuth } from '@angular/fire/auth';
import { provideFirestore,getFirestore } from '@angular/fire/firestore';
import {
provideAnalytics,
getAnalytics,
ScreenTrackingService,
UserTrackingService,
} from '@angular/fire/analytics';
import { provideAuth, getAuth } from '@angular/fire/auth';
import { provideFirestore, getFirestore } from '@angular/fire/firestore';

@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, provideFirebaseApp(() => initializeApp(environment.firebase)), provideAnalytics(() => getAnalytics()), provideAuth(() => getAuth()), provideFirestore(() => getFirestore())],
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, ScreenTrackingService,UserTrackingService],
imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
provideFirebaseApp(() => initializeApp(environment.firebase)),
provideAnalytics(() => getAnalytics()),
provideAuth(() => getAuth()),
provideFirestore(() => getFirestore()),
],
providers: [
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
ScreenTrackingService,
UserTrackingService,
],
bootstrap: [AppComponent],
})
export class AppModule {}
17 changes: 17 additions & 0 deletions src/app/auth/login/login-routing.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

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

const routes: Routes = [
{
path: '',
component: LoginPage
}
];

@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class LoginPageRoutingModule {}
16 changes: 16 additions & 0 deletions src/app/auth/login/login.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

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

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

import { LoginPage } from './login.page';
import { SharedModule } from 'src/app/shared/shared.module';

@NgModule({
imports: [SharedModule, LoginPageRoutingModule],
declarations: [LoginPage],
})
export class LoginPageModule {}
39 changes: 39 additions & 0 deletions src/app/auth/login/login.page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<ion-header>
<ion-toolbar>
<ion-title>Authenticate yourself!</ion-title>
</ion-toolbar>
</ion-header>

<ion-content>
<form [formGroup]="form" action="submit">
<ion-list>
<ion-item>
<ion-label>Email:</ion-label>
<ion-input
formControlName="email"
type="email"
placeholder="email@domain.com"
></ion-input>
</ion-item>
<ion-item>
<ion-label>Password:</ion-label>
<ion-input formControlName="password" type="password"></ion-input>
</ion-item>
</ion-list>
<ion-button
expand="block"
[disabled]="form.invalid"
(click)="login()"
color="primary"
>Log In</ion-button
>
<hr />
<ion-button
expand="block"
[disabled]="form.invalid"
(click)="register()"
color="secondary"
>Register</ion-button
>
</form>
</ion-content>
4 changes: 4 additions & 0 deletions src/app/auth/login/login.page.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
form {
margin: auto;
max-width: 500px;
}
24 changes: 24 additions & 0 deletions src/app/auth/login/login.page.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';

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

describe('LoginPage', () => {
let component: LoginPage;
let fixture: ComponentFixture<LoginPage>;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ LoginPage ],
imports: [IonicModule.forRoot()]
}).compileComponents();

fixture = TestBed.createComponent(LoginPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));

it('should create', () => {
expect(component).toBeTruthy();
});
});
70 changes: 70 additions & 0 deletions src/app/auth/login/login.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// NOTE this is a dual purpose login/register page. Usually you'd split the two obviously but for the sake of time...

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

@Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
form = new FormGroup({
email: new FormControl<string>('', [Validators.required, Validators.email]),
password: new FormControl<string>('', [
Validators.required,
Validators.minLength(8),
]),
});

constructor(
private auth: AuthService,
private router: Router,
private loadingService: LoadingService,
private alert: AlertController
) {}

ngOnInit() {}

async login() {
await this.loadingService.create('Logging you in...');
try {
const user = await this.auth.login(
this.form.value as { email: string; password: string }
);
this.loadingService.dismiss();
this.router.navigate(['/']);
} catch (error) {
// TODO proper handling of this error, give the Users an explanation/way to resolve
this.loadingService.dismiss();
const alert = await this.alert.create({
message: 'Failed to log you in. Check your credentials.',
buttons: ['OK'],
});
alert.present();
}
}

async register() {
await this.loadingService.create('Signing you up...');
try {
const user = await this.auth.register(
this.form.value as { email: string; password: string }
);
this.loadingService.dismiss();
this.router.navigate(['/']);
} catch (error) {
// TODO proper handling of this error, give the Users an explanation/way to resolve
this.loadingService.dismiss();
const alert = await this.alert.create({
message: 'Failed to register. Try again with a different email.',
buttons: ['OK'],
});
alert.present();
}
}
}
18 changes: 17 additions & 1 deletion src/app/journal/journal.page.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
<ion-menu contentId="main-content">
<ion-header>
<ion-toolbar color="tertiary">
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-button (click)="logout()" expand="block" color="light"
><ion-icon name="log-out-outline"></ion-icon>Logout</ion-button
>
</ion-content>
</ion-menu>

<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title class="cursive" color="primary">Diar.io</ion-title>
</ion-toolbar>
</ion-header>

<ion-content>
<ion-content id="main-content">
<section class="title">
<ion-text color="primary">
<h1 class="cursive">Welcome to Diar.io!</h1>
Expand Down
19 changes: 18 additions & 1 deletion src/app/journal/journal.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@ import { Component, OnInit } from '@angular/core';
import { Base } from '../shared/components/base.component';
import { ModalController } from '@ionic/angular';
import { WriteEntryPage } from './write-entry/write-entry.page';
import { AuthService } from '../services/auth.service';
import { LoadingService } from '../services/loading.service';
import { Router } from '@angular/router';

@Component({
selector: 'app-journal',
templateUrl: './journal.page.html',
styleUrls: ['./journal.page.scss'],
})
export class JournalPage extends Base implements OnInit {
constructor(private modalController: ModalController) {
constructor(
private modalController: ModalController,
private auth: AuthService,
private loading: LoadingService,
private router: Router
) {
super();
}

Expand All @@ -22,4 +30,13 @@ export class JournalPage extends Base implements OnInit {
});
modal.present();
}

async logout() {
await this.loading.create('Logging you out...');
try {
await this.auth.logout();
this.router.navigate(['/', 'login']);
} catch (error) {}
this.loading.dismiss();
}
}
16 changes: 16 additions & 0 deletions src/app/services/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { AuthService } from './auth.service';

describe('AuthService', () => {
let service: AuthService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AuthService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
39 changes: 39 additions & 0 deletions src/app/services/auth.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Injectable } from '@angular/core';
import {
Auth,
UserCredential,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
} from '@angular/fire/auth';

@Injectable({
providedIn: 'root',
})
export class AuthService {
constructor(private auth: Auth) {}

register(creds: {
email: string;
password: string;
}): Promise<UserCredential> {
// try {

// } catch (error) {

// }
return createUserWithEmailAndPassword(
this.auth,
creds.email,
creds.password
);
}

login(creds: { email: string; password: string }): Promise<UserCredential> {
return signInWithEmailAndPassword(this.auth, creds.email, creds.password);
}

logout(): Promise<void> {
return signOut(this.auth);
}
}

0 comments on commit 0764094

Please sign in to comment.