Skip to content

Commit eaa7e55

Browse files
committed
Angular Security course
1 parent 13a035a commit eaa7e55

14 files changed

+110
-17
lines changed

package-lock.json

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/database-data.ts

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,26 @@
1-
2-
31
import {DbUser} from "./db-user";
42

5-
export const USERS: {[key:number]:DbUser} = {};
3+
export const USERS: { [key: number]: DbUser } = {
4+
1: {
5+
id: 1,
6+
email: 'admin@gmail.com',
7+
// ADMIN user (password is Password10) can read all lessons and also can login on behalf of other users
8+
passwordDigest: '$argon2i$v=19$m=4096,t=3,p=1$PcKtsL4a6+xuPbMCKPep7A$rrFO2lKZcAVguIMaSGaf3hMrKtb6wUG4zN/wDG+xNts',
9+
roles: [
10+
'READ:LESSONS'
11+
]
12+
},
13+
2: {
14+
id: 1,
15+
email: 'user@gmail.com',
16+
// normal user (password is Password10), does not have access to login as another user functionality
17+
passwordDigest: '$argon2i$v=19$m=4096,t=3,p=1$PcKtsL4a6+xuPbMCKPep7A$rrFO2lKZcAVguIMaSGaf3hMrKtb6wUG4zN/wDG+xNts',
18+
roles: [
19+
'READ:LESSONS',
20+
'ADMIN'
21+
]
22+
}
23+
};
624

725

826
export const LESSONS = {

server/database.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class InMemoryDatabase {
2929
const user: DbUser = {
3030
id,
3131
email,
32-
passwordDigest
32+
passwordDigest,
33+
roles: ["READ:LESSONS"]
3334
};
3435

3536
USERS[id] = user;

server/db-user.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
export interface DbUser {
44
id:number;
55
email:string;
6-
passwordDigest:string;
6+
passwordDigest:string,
7+
roles: string[]
78
}

server/get-user.route.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function getUser(req:Request, res:Response) {
1010
const user = db.findUserById(req["userId"]);
1111

1212
if (user) {
13-
res.status(200).json({email:user.email, id:user.id});
13+
res.status(200).json({email:user.email, id:user.id, roles: user.roles});
1414
}
1515
else {
1616
res.sendStatus(204);

src/app/admin/admin.component.css

Whitespace-only changes.

src/app/admin/admin.component.html

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
<form autocomplete="off" novalidate [formGroup]="form">
3+
4+
<fieldset>
5+
<legend>Login As User</legend>
6+
<div class="form-field">
7+
<label>Email:</label>
8+
<input name="userEmail" formControlName="userEmail">
9+
</div>
10+
</fieldset>
11+
12+
<div class="form-buttons">
13+
<button class="button button-primary" (click)="loginAsUser()">Login As User</button>
14+
</div>
15+
16+
17+
</form>

src/app/admin/admin.component.ts

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Component, OnInit } from '@angular/core';
2+
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
3+
import {AuthService} from "../services/auth.service";
4+
import {Router} from "@angular/router";
5+
6+
@Component({
7+
selector: 'admin',
8+
templateUrl: './admin.component.html',
9+
styleUrls: ['./admin.component.css', '../common/forms.css']
10+
})
11+
export class AdminComponent {
12+
13+
form:FormGroup;
14+
15+
constructor(private fb:FormBuilder, private authService: AuthService, private router: Router) {
16+
17+
this.form = this.fb.group({
18+
userEmail: ['user@gmail.com',Validators.required]
19+
});
20+
}
21+
22+
23+
loginAsUser() {
24+
25+
const val = this.form.value;
26+
27+
if (val.email && val.password) {
28+
29+
this.authService.loginAsUser(val.email)
30+
.subscribe(
31+
() => {
32+
console.log("Logged in as user with email " + val.email);
33+
this.router.navigateByUrl('/');
34+
}
35+
);
36+
37+
}
38+
39+
40+
}
41+
42+
}

src/app/app.component.html

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
<li>
1010
<a routerLink="/lessons">Lessons</a>
1111
</li>
12+
<li>
13+
<a routerLink="/admin">ADMIN</a>
14+
</li>
1215
<li *ngIf="isLoggedOut$ | async">
1316
<a routerLink="/signup">Sign Up</a>
1417
</li>

src/app/app.module.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,16 @@ import 'rxjs/add/operator/filter';
2121
import 'rxjs/add/operator/catch';
2222

2323
import 'rxjs/add/observable/of';
24+
import { AdminComponent } from './admin/admin.component';
2425

2526

2627
@NgModule({
2728
declarations: [
2829
AppComponent,
2930
LessonsComponent,
3031
LoginComponent,
31-
SignupComponent
32+
SignupComponent,
33+
AdminComponent
3234
],
3335
imports: [
3436
BrowserModule,

src/app/login/login.component.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class LoginComponent implements OnInit {
2121
constructor(private fb:FormBuilder, private authService: AuthService, private router: Router) {
2222

2323
this.form = this.fb.group({
24-
email: ['test@gmail.com',Validators.required],
24+
email: ['user@gmail.com',Validators.required],
2525
password: ['Password10',Validators.required]
2626
});
2727

src/app/model/user.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

2-
export interface User {
32

3+
export interface User {
44
id:number;
55
email:string;
6-
6+
roles: string[];
77
}

src/app/routes.config.ts

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {Routes} from '@angular/router';
22
import {LessonsComponent} from "./lessons/lessons.component";
33
import {LoginComponent} from "./login/login.component";
44
import {SignupComponent} from "./signup/signup.component";
5+
import {AdminComponent} from "./admin/admin.component";
56

67
export const routesConfig: Routes = [
78
{
@@ -16,6 +17,10 @@ export const routesConfig: Routes = [
1617
path: 'signup',
1718
component: SignupComponent
1819
},
20+
{
21+
path: 'admin',
22+
component: AdminComponent
23+
},
1924
{
2025
path: '',
2126
redirectTo:'/lessons',

src/app/services/auth.service.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import {BehaviorSubject} from "rxjs/BehaviorSubject";
66

77
export const ANONYMOUS_USER: User = {
88
id: undefined,
9-
email: ''
9+
email: '',
10+
roles: []
1011
}
1112

1213

@@ -26,9 +27,6 @@ export class AuthService {
2627
.subscribe(user => this.subject.next(user ? user : ANONYMOUS_USER));
2728
}
2829

29-
30-
31-
3230
signUp(email:string, password:string ) {
3331

3432
return this.http.post<User>('/api/signup', {email, password})
@@ -42,6 +40,12 @@ export class AuthService {
4240
.do(user => this.subject.next(user));
4341
}
4442

43+
loginAsUser(email:string) {
44+
return this.http.post<User>('/api/admin', {email})
45+
.shareReplay()
46+
.do(user => this.subject.next(user));
47+
}
48+
4549
logout() : Observable<any> {
4650
return this.http.post('/api/logout', null)
4751
.shareReplay()

0 commit comments

Comments
 (0)