diff options
-rw-r--r-- | client/src/app/+login/login.component.ts | 18 | ||||
-rw-r--r-- | client/src/app/core/routing/redirect.service.ts | 71 |
2 files changed, 68 insertions, 21 deletions
diff --git a/client/src/app/+login/login.component.ts b/client/src/app/+login/login.component.ts index 73bd41ab4..96754b782 100644 --- a/client/src/app/+login/login.component.ts +++ b/client/src/app/+login/login.component.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | 1 | ||
2 | import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core' | 2 | import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core' |
3 | import { ActivatedRoute } from '@angular/router' | 3 | import { ActivatedRoute, Router } from '@angular/router' |
4 | import { AuthService, Notifier, RedirectService, SessionStorageService, UserService } from '@app/core' | 4 | import { AuthService, Notifier, RedirectService, SessionStorageService, UserService } from '@app/core' |
5 | import { HooksService } from '@app/core/plugins/hooks.service' | 5 | import { HooksService } from '@app/core/plugins/hooks.service' |
6 | import { LOGIN_PASSWORD_VALIDATOR, LOGIN_USERNAME_VALIDATOR } from '@app/shared/form-validators/login-validators' | 6 | import { LOGIN_PASSWORD_VALIDATOR, LOGIN_USERNAME_VALIDATOR } from '@app/shared/form-validators/login-validators' |
@@ -49,7 +49,8 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni | |||
49 | private redirectService: RedirectService, | 49 | private redirectService: RedirectService, |
50 | private notifier: Notifier, | 50 | private notifier: Notifier, |
51 | private hooks: HooksService, | 51 | private hooks: HooksService, |
52 | private storage: SessionStorageService | 52 | private storage: SessionStorageService, |
53 | private router: Router | ||
53 | ) { | 54 | ) { |
54 | super() | 55 | super() |
55 | } | 56 | } |
@@ -92,7 +93,10 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni | |||
92 | return | 93 | return |
93 | } | 94 | } |
94 | 95 | ||
95 | this.storage.setItem(LoginComponent.SESSION_STORAGE_REDIRECT_URL_KEY, this.redirectService.getPreviousUrl()) | 96 | const previousUrl = this.redirectService.getPreviousUrl() |
97 | if (previousUrl && previousUrl !== '/') { | ||
98 | this.storage.setItem(LoginComponent.SESSION_STORAGE_REDIRECT_URL_KEY, previousUrl) | ||
99 | } | ||
96 | } | 100 | } |
97 | 101 | ||
98 | ngAfterViewInit () { | 102 | ngAfterViewInit () { |
@@ -157,7 +161,13 @@ The link will expire within 1 hour.` | |||
157 | this.authService.login(username, null, token) | 161 | this.authService.login(username, null, token) |
158 | .subscribe({ | 162 | .subscribe({ |
159 | next: () => { | 163 | next: () => { |
160 | this.redirectService.redirectToPreviousRoute(this.storage.getItem(LoginComponent.SESSION_STORAGE_REDIRECT_URL_KEY)) | 164 | const redirectUrl = this.storage.getItem(LoginComponent.SESSION_STORAGE_REDIRECT_URL_KEY) |
165 | if (redirectUrl) { | ||
166 | this.storage.removeItem(LoginComponent.SESSION_STORAGE_REDIRECT_URL_KEY) | ||
167 | return this.router.navigateByUrl(redirectUrl) | ||
168 | } | ||
169 | |||
170 | this.redirectService.redirectToLatestSessionRoute() | ||
161 | }, | 171 | }, |
162 | 172 | ||
163 | error: err => { | 173 | error: err => { |
diff --git a/client/src/app/core/routing/redirect.service.ts b/client/src/app/core/routing/redirect.service.ts index d4cb0436e..2b8cbaa59 100644 --- a/client/src/app/core/routing/redirect.service.ts +++ b/client/src/app/core/routing/redirect.service.ts | |||
@@ -1,9 +1,15 @@ | |||
1 | import * as debug from 'debug' | ||
1 | import { Injectable } from '@angular/core' | 2 | import { Injectable } from '@angular/core' |
2 | import { NavigationCancel, NavigationEnd, Router } from '@angular/router' | 3 | import { NavigationCancel, NavigationEnd, Router } from '@angular/router' |
3 | import { ServerService } from '../server' | 4 | import { ServerService } from '../server' |
5 | import { SessionStorageService } from '../wrappers/storage.service' | ||
6 | |||
7 | const logger = debug('peertube:router:RedirectService') | ||
4 | 8 | ||
5 | @Injectable() | 9 | @Injectable() |
6 | export class RedirectService { | 10 | export class RedirectService { |
11 | private static SESSION_STORAGE_LATEST_SESSION_URL_KEY = 'redirect-latest-session-url' | ||
12 | |||
7 | // Default route could change according to the instance configuration | 13 | // Default route could change according to the instance configuration |
8 | static INIT_DEFAULT_ROUTE = '/videos/trending' | 14 | static INIT_DEFAULT_ROUTE = '/videos/trending' |
9 | static INIT_DEFAULT_TRENDING_ALGORITHM = 'most-viewed' | 15 | static INIT_DEFAULT_TRENDING_ALGORITHM = 'most-viewed' |
@@ -11,13 +17,16 @@ export class RedirectService { | |||
11 | private previousUrl: string | 17 | private previousUrl: string |
12 | private currentUrl: string | 18 | private currentUrl: string |
13 | 19 | ||
20 | private latestSessionUrl: string | ||
21 | |||
14 | private redirectingToHomepage = false | 22 | private redirectingToHomepage = false |
15 | private defaultTrendingAlgorithm = RedirectService.INIT_DEFAULT_TRENDING_ALGORITHM | 23 | private defaultTrendingAlgorithm = RedirectService.INIT_DEFAULT_TRENDING_ALGORITHM |
16 | private defaultRoute = RedirectService.INIT_DEFAULT_ROUTE | 24 | private defaultRoute = RedirectService.INIT_DEFAULT_ROUTE |
17 | 25 | ||
18 | constructor ( | 26 | constructor ( |
19 | private router: Router, | 27 | private router: Router, |
20 | private serverService: ServerService | 28 | private serverService: ServerService, |
29 | private storage: SessionStorageService | ||
21 | ) { | 30 | ) { |
22 | // The config is first loaded from the cache so try to get the default route | 31 | // The config is first loaded from the cache so try to get the default route |
23 | const config = this.serverService.getHTMLConfig() | 32 | const config = this.serverService.getHTMLConfig() |
@@ -28,12 +37,22 @@ export class RedirectService { | |||
28 | this.defaultTrendingAlgorithm = config.trending.videos.algorithms.default | 37 | this.defaultTrendingAlgorithm = config.trending.videos.algorithms.default |
29 | } | 38 | } |
30 | 39 | ||
40 | this.latestSessionUrl = this.storage.getItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY) | ||
41 | this.storage.removeItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY) | ||
42 | |||
43 | logger('Loaded latest session URL %s', this.latestSessionUrl) | ||
44 | |||
31 | // Track previous url | 45 | // Track previous url |
32 | this.currentUrl = this.router.url | 46 | this.currentUrl = this.router.url |
33 | router.events.subscribe(event => { | 47 | router.events.subscribe(event => { |
34 | if (event instanceof NavigationEnd || event instanceof NavigationCancel) { | 48 | if (event instanceof NavigationEnd || event instanceof NavigationCancel) { |
35 | this.previousUrl = this.currentUrl | 49 | this.previousUrl = this.currentUrl |
36 | this.currentUrl = event.url | 50 | this.currentUrl = event.url |
51 | |||
52 | logger('Previous URL is %s, current URL is %s', this.previousUrl, this.currentUrl) | ||
53 | logger('Setting %s as latest URL in session storage.', this.currentUrl) | ||
54 | |||
55 | this.storage.setItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY, this.currentUrl) | ||
37 | } | 56 | } |
38 | }) | 57 | }) |
39 | } | 58 | } |
@@ -46,26 +65,16 @@ export class RedirectService { | |||
46 | return this.defaultTrendingAlgorithm | 65 | return this.defaultTrendingAlgorithm |
47 | } | 66 | } |
48 | 67 | ||
49 | getPreviousUrl () { | 68 | redirectToLatestSessionRoute () { |
50 | return this.previousUrl | 69 | return this.doRedirect(this.latestSessionUrl) |
51 | } | 70 | } |
52 | 71 | ||
53 | redirectToPreviousRoute (fallbackRoute?: string) { | 72 | redirectToPreviousRoute (fallbackRoute?: string) { |
54 | const exceptions = [ | 73 | return this.doRedirect(this.previousUrl, fallbackRoute) |
55 | '/verify-account', | 74 | } |
56 | '/reset-password' | ||
57 | ] | ||
58 | |||
59 | if (this.previousUrl && this.previousUrl !== '/') { | ||
60 | const isException = exceptions.find(e => this.previousUrl.startsWith(e)) | ||
61 | if (!isException) return this.router.navigateByUrl(this.previousUrl) | ||
62 | } | ||
63 | |||
64 | if (fallbackRoute) { | ||
65 | return this.router.navigateByUrl(fallbackRoute) | ||
66 | } | ||
67 | 75 | ||
68 | return this.redirectToHomepage() | 76 | getPreviousUrl () { |
77 | return this.previousUrl | ||
69 | } | 78 | } |
70 | 79 | ||
71 | redirectToHomepage (skipLocationChange = false) { | 80 | redirectToHomepage (skipLocationChange = false) { |
@@ -91,4 +100,32 @@ export class RedirectService { | |||
91 | }) | 100 | }) |
92 | 101 | ||
93 | } | 102 | } |
103 | |||
104 | private doRedirect (redirectUrl: string, fallbackRoute?: string) { | ||
105 | logger('Redirecting on %s', redirectUrl) | ||
106 | |||
107 | if (this.isValidRedirection(redirectUrl)) { | ||
108 | return this.router.navigateByUrl(redirectUrl) | ||
109 | } | ||
110 | |||
111 | logger('%s is not a valid redirection, try fallback route %s', redirectUrl, fallbackRoute) | ||
112 | if (fallbackRoute) { | ||
113 | return this.router.navigateByUrl(fallbackRoute) | ||
114 | } | ||
115 | |||
116 | logger('There was no fallback route, redirecting to homepage') | ||
117 | return this.redirectToHomepage() | ||
118 | } | ||
119 | |||
120 | private isValidRedirection (redirectUrl: string) { | ||
121 | const exceptions = [ | ||
122 | '/verify-account', | ||
123 | '/reset-password', | ||
124 | '/login' | ||
125 | ] | ||
126 | |||
127 | if (!redirectUrl || redirectUrl === '/') return false | ||
128 | |||
129 | return exceptions.every(e => !redirectUrl.startsWith(e)) | ||
130 | } | ||
94 | } | 131 | } |