aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/core/routing/redirect.service.ts
blob: 575b3b2a18322c9da5d10d3ec9a71a91cad410c7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import * as debug from 'debug'
import { Injectable } from '@angular/core'
import { NavigationCancel, NavigationEnd, Router } from '@angular/router'
import { logger } from '@root-helpers/logger'
import { ServerService } from '../server'
import { SessionStorageService } from '../wrappers/storage.service'

const debugLogger = debug('peertube:router:RedirectService')

@Injectable()
export class RedirectService {
  private static SESSION_STORAGE_LATEST_SESSION_URL_KEY = 'redirect-latest-session-url'

  // Default route could change according to the instance configuration
  static INIT_DEFAULT_ROUTE = '/videos/trending'
  static INIT_DEFAULT_TRENDING_ALGORITHM = 'most-viewed'

  private previousUrl: string
  private currentUrl: string

  private latestSessionUrl: string

  private redirectingToHomepage = false
  private defaultTrendingAlgorithm = RedirectService.INIT_DEFAULT_TRENDING_ALGORITHM
  private defaultRoute = RedirectService.INIT_DEFAULT_ROUTE

  constructor (
    private router: Router,
    private serverService: ServerService,
    private storage: SessionStorageService
  ) {
    // The config is first loaded from the cache so try to get the default route
    const config = this.serverService.getHTMLConfig()
    if (config?.instance?.defaultClientRoute) {
      this.defaultRoute = config.instance.defaultClientRoute
    }
    if (config?.trending?.videos?.algorithms?.default) {
      this.defaultTrendingAlgorithm = config.trending.videos.algorithms.default
    }

    this.latestSessionUrl = this.storage.getItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY)
    this.storage.removeItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY)

    debugLogger('Loaded latest session URL %s', this.latestSessionUrl)

    // Track previous url
    this.currentUrl = this.router.url
    router.events.subscribe(event => {
      if (event instanceof NavigationEnd || event instanceof NavigationCancel) {
        if ([ '/401', '/404' ].includes(event.url)) return

        this.previousUrl = this.currentUrl
        this.currentUrl = event.url

        debugLogger('Previous URL is %s, current URL is %s', this.previousUrl, this.currentUrl)
        debugLogger('Setting %s as latest URL in session storage.', this.currentUrl)

        this.storage.setItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY, this.currentUrl)
      }
    })
  }

  getDefaultRoute () {
    return this.defaultRoute
  }

  getDefaultTrendingAlgorithm () {
    return this.defaultTrendingAlgorithm
  }

  redirectToLatestSessionRoute () {
    return this.doRedirect(this.latestSessionUrl)
  }

  redirectToPreviousRoute (fallbackRoute?: string) {
    return this.doRedirect(this.previousUrl, fallbackRoute)
  }

  getPreviousUrl () {
    return this.previousUrl
  }

  redirectToHomepage (skipLocationChange = false) {
    if (this.redirectingToHomepage) return

    this.redirectingToHomepage = true

    logger.info(`Redirecting to ${this.defaultRoute}...`)

    this.router.navigateByUrl(this.defaultRoute, { skipLocationChange })
        .then(() => this.redirectingToHomepage = false)
        .catch(() => {
          this.redirectingToHomepage = false

          logger.error(`Cannot navigate to ${this.defaultRoute}, resetting default route to ${RedirectService.INIT_DEFAULT_ROUTE}`)

          this.defaultRoute = RedirectService.INIT_DEFAULT_ROUTE
          return this.router.navigateByUrl(this.defaultRoute, { skipLocationChange })
        })

  }

  private doRedirect (redirectUrl: string, fallbackRoute?: string) {
    debugLogger('Redirecting on %s', redirectUrl)

    if (this.isValidRedirection(redirectUrl)) {
      return this.router.navigateByUrl(redirectUrl)
    }

    debugLogger('%s is not a valid redirection, try fallback route %s', redirectUrl, fallbackRoute)
    if (fallbackRoute) {
      return this.router.navigateByUrl(fallbackRoute)
    }

    debugLogger('There was no fallback route, redirecting to homepage')
    return this.redirectToHomepage()
  }

  private isValidRedirection (redirectUrl: string) {
    const exceptions = [
      '/verify-account',
      '/reset-password',
      '/login'
    ]

    if (!redirectUrl || redirectUrl === '/') return false

    return exceptions.every(e => !redirectUrl.startsWith(e))
  }
}