Account management works but the app is reloaded multiple times

This commit is contained in:
Zoe Roux 2020-03-08 23:11:24 +01:00
parent 45f2b5b641
commit b436d48826
17 changed files with 127 additions and 83 deletions

View File

@ -85,23 +85,6 @@
"browserTarget": "Kyoo:build" "browserTarget": "Kyoo:build"
} }
}, },
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.sass"
],
"scripts": []
}
},
"lint": { "lint": {
"builder": "@angular-devkit/build-angular:tslint", "builder": "@angular-devkit/build-angular:tslint",
"options": { "options": {
@ -114,18 +97,6 @@
"**/node_modules/**" "**/node_modules/**"
] ]
} }
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "Kyoo:serve"
},
"configurations": {
"production": {
"devServerTarget": "Kyoo:serve:production"
}
}
} }
} }
}}, }},

View File

@ -5,9 +5,7 @@
"ng": "ng", "ng": "ng",
"start": "ng serve", "start": "ng serve",
"build": "ng build", "build": "ng build",
"test": "ng test", "lint": "ng lint"
"lint": "ng lint",
"e2e": "ng e2e"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {

View File

@ -13,6 +13,7 @@ import { ShowResolverService } from './services/show-resolver.service';
import { StreamResolverService } from "./services/stream-resolver.service"; import { StreamResolverService } from "./services/stream-resolver.service";
import { ShowDetailsComponent } from './show-details/show-details.component'; import { ShowDetailsComponent } from './show-details/show-details.component';
import {LoginComponent} from "./login/login.component"; import {LoginComponent} from "./login/login.component";
import {LoggedComponent} from "./logged/logged.component";
const routes: Routes = [ const routes: Routes = [
{ path: "browse", component: BrowseComponent, pathMatch: "full", resolve: { shows: LibraryResolverService } }, { path: "browse", component: BrowseComponent, pathMatch: "full", resolve: { shows: LibraryResolverService } },
@ -23,6 +24,7 @@ const routes: Routes = [
{ path: "watch/:item", component: PlayerComponent, resolve: { item: StreamResolverService } }, { path: "watch/:item", component: PlayerComponent, resolve: { item: StreamResolverService } },
{ path: "search/:query", component: SearchComponent, resolve: { items: SearchResolverService } }, { path: "search/:query", component: SearchComponent, resolve: { items: SearchResolverService } },
{ path: "login", component: LoginComponent }, { path: "login", component: LoginComponent },
{ path: "logged", component: LoggedComponent },
{ path: "**", component: NotFoundComponent } { path: "**", component: NotFoundComponent }
]; ];

View File

@ -19,11 +19,22 @@
<input placeholder="Search" id="search" type="search" (input)="onUpdateValue($event)"/> <input placeholder="Search" id="search" type="search" (input)="onUpdateValue($event)"/>
<mat-icon matTooltipPosition="below" matTooltip="Search" (click)="openSearch()">search</mat-icon> <mat-icon matTooltipPosition="below" matTooltip="Search" (click)="openSearch()">search</mat-icon>
</li> </li>
<li class="nav-item"> <li class="nav-item" *ngIf="!isLoggedIn(); else accountDrop">
<a class="icon" routerLink="/login" routerLinkActive="active" matTooltipPosition="below" matTooltip="Login"> <a class="icon" (click)="login()" matTooltipPosition="below" matTooltip="Login">
<mat-icon>account_circle</mat-icon> <mat-icon>account_circle</mat-icon>
</a> </a>
</li> </li>
<ng-template #accountDrop>
<li class="nav-item">
<button mat-icon-button [matMenuTriggerFor]="accountMenu" class="icon" matTooltipPosition="below" [matTooltip]="authManager.user.profile.name">
<mat-icon>more_vert</mat-icon>
</button>
</li>
<mat-menu #accountMenu="matMenu">
<button mat-menu-item>Settings</button>
<button mat-menu-item>Logout</button>
</mat-menu>
</ng-template>
</ul> </ul>
</nav> </nav>
<mat-progress-bar *ngIf="this.isLoading" color="accent" mode="indeterminate"> </mat-progress-bar> <mat-progress-bar *ngIf="this.isLoading" color="accent" mode="indeterminate"> </mat-progress-bar>

View File

@ -71,7 +71,6 @@ input::-webkit-search-cancel-button
display: none; display: none;
} }
.icon .icon
{ {
padding: 8px; padding: 8px;

View File

@ -3,6 +3,7 @@ import { HttpClient } from '@angular/common/http';
import { Event, Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router'; import { Event, Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router';
import * as $ from "jquery"; import * as $ from "jquery";
import { Location } from "@angular/common"; import { Location } from "@angular/common";
import {AuthService} from "./services/auth.service";
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -14,7 +15,7 @@ export class AppComponent
libraries: Library[]; libraries: Library[];
isLoading: boolean = false; isLoading: boolean = false;
constructor(http: HttpClient, private router: Router, private location: Location) constructor(http: HttpClient, private router: Router, private location: Location, private authManager: AuthService)
{ {
http.get<Library[]>("api/libraries").subscribe(result => http.get<Library[]>("api/libraries").subscribe(result =>
{ {
@ -66,6 +67,16 @@ export class AppComponent
this.location.back(); this.location.back();
} }
} }
isLoggedIn(): boolean
{
return this.authManager.isLoggedIn();
}
login()
{
this.authManager.login();
}
} }
interface Library interface Library

View File

@ -30,6 +30,7 @@ import { MatFormFieldModule } from "@angular/material/form-field";
import {MatTabsModule} from "@angular/material/tabs"; import {MatTabsModule} from "@angular/material/tabs";
import {PasswordValidator} from "./misc/password-validator"; import {PasswordValidator} from "./misc/password-validator";
import {MatCheckboxModule} from "@angular/material/checkbox"; import {MatCheckboxModule} from "@angular/material/checkbox";
import { LoggedComponent } from './logged/logged.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -44,7 +45,8 @@ import {MatCheckboxModule} from "@angular/material/checkbox";
PeopleListComponent, PeopleListComponent,
ShowsListComponent, ShowsListComponent,
LoginComponent, LoginComponent,
PasswordValidator PasswordValidator,
LoggedComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@ -0,0 +1 @@
<p>logged works!</p>

View File

View File

@ -0,0 +1,21 @@
import { Component, OnInit } from '@angular/core';
import {AuthService} from "../services/auth.service";
import {Router} from "@angular/router";
@Component({
selector: 'app-logged',
templateUrl: './logged.component.html',
styleUrls: ['./logged.component.scss']
})
export class LoggedComponent implements OnInit
{
constructor(private authManager: AuthService, private router: Router) { }
ngOnInit()
{
this.authManager.loginCallback().then(result =>
{
// this.router.navigateByUrl("");
});
}
}

View File

@ -35,9 +35,9 @@
</div> </div>
</form> </form>
</mat-tab> </mat-tab>
<mat-tab label="Signin"> <mat-tab label="Register">
<br/> <br/>
<form #signinForm="ngForm" (ngSubmit)="signin()"> <form #signinForm="ngForm" (ngSubmit)="register()">
<mat-card-content> <mat-card-content>
<mat-form-field appearance="outline" class="w-75"> <mat-form-field appearance="outline" class="w-75">
<mat-label>Email</mat-label> <mat-label>Email</mat-label>

View File

@ -1,6 +1,10 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import {AuthService} from "../services/auth.service"; import {AuthService} from "../services/auth.service";
import {ActivatedRoute, Router} from "@angular/router"; import {ActivatedRoute, Router} from "@angular/router";
import {catchError} from "rxjs/operators";
import {EMPTY} from "rxjs";
import {HttpClient} from "@angular/common/http";
import {MatSnackBar} from "@angular/material/snack-bar";
@Component({ @Component({
selector: 'app-login', selector: 'app-login',
@ -12,25 +16,29 @@ export class LoginComponent
loginInformation: {username: string, password: string, stayLoggedIn: boolean} = {username: "", password: "", stayLoggedIn: false}; loginInformation: {username: string, password: string, stayLoggedIn: boolean} = {username: "", password: "", stayLoggedIn: false};
signinInformation: {email: string, username: string, password: string} = {email: "", username: "", password: ""}; signinInformation: {email: string, username: string, password: string} = {email: "", username: "", password: ""};
hidePassword: boolean = true; hidePassword: boolean = true;
redirectURI: string = "/"; redirectURI: string;
constructor(private authService: AuthService, private router: Router, private route: ActivatedRoute) constructor(private router: Router, private route: ActivatedRoute, private http: HttpClient, private snackBar: MatSnackBar)
{ {
if (this.route.snapshot.queryParams["redirectURI"]) if (this.route.snapshot.queryParams["ReturnUrl"])
this.redirectURI = this.route.snapshot.queryParams["redirectURI"]; this.redirectURI = this.route.snapshot.queryParams["ReturnUrl"];
if (this.route.snapshot.queryParams["otac"]) if (this.route.snapshot.queryParams["otac"])
this.useOTAC(this.route.snapshot.queryParams["otac"]); this.useOTAC(this.route.snapshot.queryParams["otac"]);
} }
async login() async login()
{ {
this.authService.login(this.loginInformation) this.http.post("/api/account/login", this.loginInformation).pipe(catchError((error =>
.subscribe(() => {
{ console.log(error.status + " - " + error.message);
this.router.navigateByUrl(this.redirectURI); this.snackBar.open(`An unknown error occured: ${error.message}.`, null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
}, error => { return EMPTY;
console.log("Login error: " + error); }))).subscribe(() =>
}); {
window.location.href = this.redirectURI;
}, error => {
console.log("Login error: " + error);
});
} }
useOTAC(otac: string) useOTAC(otac: string)
@ -38,14 +46,14 @@ export class LoginComponent
console.log("Got an OTAC: " + otac); console.log("Got an OTAC: " + otac);
} }
async signin() async register()
{ {
this.authService.register(this.signinInformation) // @ts-ignore
.subscribe(result => this.http.post<string>("/api/account/register", this.signinInformation, {responseType: "text"}).pipe(catchError((error =>
{ {
this.useOTAC(result); console.log(error.status + " - " + error.message);
}, error => { this.snackBar.open(`An unknown error occured: ${error.message}.`, null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
console.log("Register error: " + error); return EMPTY;
}); }))).subscribe(otac => { this.useOTAC(otac); });
} }
} }

View File

@ -1,9 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { UserManager, UserManagerSettings, User } from 'oidc-client'; import {UserManager, UserManagerSettings, User, Profile} from 'oidc-client';
import {HttpClient} from "@angular/common/http";
import { catchError } from 'rxjs/operators';
import {EMPTY, Observable} from "rxjs";
import {MatSnackBar} from "@angular/material/snack-bar";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -13,45 +9,52 @@ export class AuthService
user: User | null; user: User | null;
private _userManager = new UserManager(this.getClientSettings()); private _userManager = new UserManager(this.getClientSettings());
constructor(private http: HttpClient, private snackBar: MatSnackBar) constructor()
{ {
this._userManager.getUser().then(user => this._userManager.getUser().then(user =>
{ {
this.user = user; this.user = user;
if (user) if (user)
console.log("Logged in as: " + user.profile.name); console.log("Logged in as: " + user.profile.name);
else
console.log("Not logged in.");
}); });
} }
login(loginInformation: any) isLoggedIn(): boolean
{ {
return this.http.post("/api/account/login", loginInformation).pipe(catchError((error => return this.user != null && !this.user.expired;
{
console.log(error.status + " - " + error.message);
this.snackBar.open(`An unknown error occured: ${error.message}.`, null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 });
return EMPTY;
})));
} }
register(userRegistration: any) : Observable<string> getClaims(): Profile
{ {
// @ts-ignore return this.user.profile;
return this.http.post<string>("/api/account/register", userRegistration, {responseType: "text"}).pipe(catchError((error => }
login()
{
return this._userManager.signinRedirect();
}
loginCallback()
{
return this._userManager.signinCallback().then(user =>
{ {
console.log(error.status + " - " + error.message); this.user = user;
this.snackBar.open(`An unknown error occured: ${error.message}.`, null, { horizontalPosition: "left", panelClass: ['snackError'], duration: 2500 }); console.log("Logged in!");
return EMPTY; });
})));
} }
getClientSettings(): UserManagerSettings getClientSettings(): UserManagerSettings
{ {
return { return {
authority: "", authority: window.location.origin,
client_id: "kyoo.webapp", client_id: "kyoo.webapp",
redirect_uri: "/logged", redirect_uri: "/logged",
response_type:"id_token token", silent_redirect_uri: "/silent",
scope:"openid profile kyoo.read" response_type: "code",
scope: "openid profile kyoo.read offline_access",
automaticSilentRenew: true
}; };
} }
} }

12
src/assets/silent.html Normal file
View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Silent renew</title>
</head>
<body>
<script>
new window.Oidc.UserManager().signinSilentCallback();
</script>
</body>
</html>

View File

@ -103,3 +103,8 @@ mat-icon
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
} }
.cdk-overlay-container
{
z-index: 2000 !important;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB