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"
}
},
"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": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
@ -114,18 +97,6 @@
"**/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",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
"lint": "ng lint"
},
"private": true,
"dependencies": {

View File

@ -13,6 +13,7 @@ import { ShowResolverService } from './services/show-resolver.service';
import { StreamResolverService } from "./services/stream-resolver.service";
import { ShowDetailsComponent } from './show-details/show-details.component';
import {LoginComponent} from "./login/login.component";
import {LoggedComponent} from "./logged/logged.component";
const routes: Routes = [
{ 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: "search/:query", component: SearchComponent, resolve: { items: SearchResolverService } },
{ path: "login", component: LoginComponent },
{ path: "logged", component: LoggedComponent },
{ path: "**", component: NotFoundComponent }
];

View File

@ -19,11 +19,22 @@
<input placeholder="Search" id="search" type="search" (input)="onUpdateValue($event)"/>
<mat-icon matTooltipPosition="below" matTooltip="Search" (click)="openSearch()">search</mat-icon>
</li>
<li class="nav-item">
<a class="icon" routerLink="/login" routerLinkActive="active" matTooltipPosition="below" matTooltip="Login">
<li class="nav-item" *ngIf="!isLoggedIn(); else accountDrop">
<a class="icon" (click)="login()" matTooltipPosition="below" matTooltip="Login">
<mat-icon>account_circle</mat-icon>
</a>
</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>
</nav>
<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;
}
.icon
{
padding: 8px;
@ -83,4 +82,4 @@ input::-webkit-search-cancel-button
cursor: pointer;
opacity: 1;
}
}
}

View File

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

View File

@ -30,6 +30,7 @@ import { MatFormFieldModule } from "@angular/material/form-field";
import {MatTabsModule} from "@angular/material/tabs";
import {PasswordValidator} from "./misc/password-validator";
import {MatCheckboxModule} from "@angular/material/checkbox";
import { LoggedComponent } from './logged/logged.component';
@NgModule({
declarations: [
@ -44,7 +45,8 @@ import {MatCheckboxModule} from "@angular/material/checkbox";
PeopleListComponent,
ShowsListComponent,
LoginComponent,
PasswordValidator
PasswordValidator,
LoggedComponent
],
imports: [
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>
</form>
</mat-tab>
<mat-tab label="Signin">
<mat-tab label="Register">
<br/>
<form #signinForm="ngForm" (ngSubmit)="signin()">
<form #signinForm="ngForm" (ngSubmit)="register()">
<mat-card-content>
<mat-form-field appearance="outline" class="w-75">
<mat-label>Email</mat-label>

View File

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

View File

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