index.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import VueRouter from 'vue-router'
  2. import HomePage from '@/views/HomePage.vue'
  3. import {HTTP} from '@/utils';
  4. import {useUserStore} from "@/store/user";
  5. const routes = [
  6. {
  7. path: '/',
  8. name: 'home',
  9. component: HomePage
  10. },
  11. {
  12. path: '/signup/:email?',
  13. name: 'signup',
  14. // route level code-splitting
  15. // this generates a separate chunk (about.[hash].js) for this route
  16. // which is lazy-loaded when the route is visited.
  17. component: () => import('@/views/SignUp.vue'),
  18. },
  19. {
  20. path: '/custom-setup/:domain',
  21. name: 'customSetup',
  22. component: () => import('@/views/DomainSetupPage.vue'),
  23. props: true,
  24. },
  25. {
  26. path: '/dyn-setup/:domain',
  27. alias: '/dynsetup/:domain',
  28. name: 'dynSetup',
  29. component: () => import('@/views/DynSetup.vue'),
  30. },
  31. {
  32. path: '/welcome/:domain?',
  33. name: 'welcome',
  34. component: () => import('@/views/WelcomePage.vue'),
  35. },
  36. {
  37. path: 'https://desec.readthedocs.io/',
  38. name: 'docs',
  39. beforeEnter(to) { location.href = to.path },
  40. },
  41. {
  42. path: 'https://talk.desec.io/',
  43. name: 'talk',
  44. beforeEnter(to) { location.href = to.path },
  45. },
  46. {
  47. path: '/confirm/:action/:code',
  48. name: 'confirmation',
  49. component: () => import('@/views/ConfirmationPage.vue')
  50. },
  51. {
  52. path: '/reset-password/:email?',
  53. name: 'reset-password',
  54. component: () => import('@/views/ResetPassword.vue'),
  55. },
  56. {
  57. path: '/totp/',
  58. name: 'totp',
  59. component: () => import('@/views/CrudListTOTP.vue'),
  60. meta: {guest: false},
  61. },
  62. {
  63. path: '/totp-verify/',
  64. name: 'TOTPVerify',
  65. component: () => import('@/views/Console/TOTPVerifyDialog.vue'),
  66. props: (route) => ({...route.params}),
  67. },
  68. {
  69. path: '/mfa/',
  70. name: 'mfa',
  71. component: () => import('@/views/MFA.vue'),
  72. meta: {guest: false},
  73. },
  74. {
  75. path: '/change-email/:email?',
  76. name: 'change-email',
  77. component: () => import('@/views/ChangeEmail.vue'),
  78. meta: {guest: false},
  79. },
  80. {
  81. path: '/delete-account/',
  82. name: 'delete-account',
  83. component: () => import('@/views/DeleteAccount.vue'),
  84. meta: {guest: false},
  85. },
  86. {
  87. path: '/donate/',
  88. name: 'donate',
  89. component: () => import('@/views/DonatePage.vue'),
  90. },
  91. {
  92. path: 'https://github.com/desec-io/desec-stack/projects?query=is%3Aopen+sort%3Aname-asc&type=classic',
  93. name: 'roadmap',
  94. beforeEnter(to) { location.href = to.path },
  95. },
  96. {
  97. path: '/impressum/',
  98. name: 'impressum',
  99. component: () => import('@/views/ImpressumPage.vue'),
  100. },
  101. {
  102. path: '/privacy-policy/',
  103. name: 'privacy-policy',
  104. component: () => import('@/views/PrivacyPolicy.vue'),
  105. },
  106. {
  107. path: '/terms/',
  108. name: 'terms',
  109. component: () => import('@/views/TermsPage.vue'),
  110. },
  111. {
  112. path: '/about/',
  113. name: 'about',
  114. component: () => import('@/views/AboutPage.vue'),
  115. },
  116. {
  117. path: '/login',
  118. name: 'login',
  119. component: () => import('@/views/LoginPage.vue'),
  120. },
  121. {
  122. path: '/tokens',
  123. name: 'tokens',
  124. component: () => import('@/views/CrudListToken.vue'),
  125. meta: {guest: false},
  126. },
  127. {
  128. path: '/domains',
  129. name: 'domains',
  130. component: () => import('@/views/CrudListDomain.vue'),
  131. meta: {guest: false},
  132. },
  133. {
  134. path: '/domains/:domain',
  135. name: 'domain',
  136. component: () => import('@/views/CrudListRecord.vue'),
  137. meta: {guest: false},
  138. },
  139. ]
  140. const router = new VueRouter({
  141. mode: 'history',
  142. base: import.meta.env.BASE_URL,
  143. scrollBehavior (to, from) {
  144. // Skip if destination full path has query parameters and differs in no other way from previous
  145. if (from && Object.keys(to.query).length) {
  146. if (to.fullPath.split('?')[0] == from.fullPath.split('?')[0]) return;
  147. }
  148. return { x: 0, y: 0 }
  149. },
  150. routes
  151. })
  152. router.beforeEach((to, from, next) => {
  153. // see if there are credentials in the session store that we don't know of
  154. let recovered = false;
  155. const user = useUserStore();
  156. if (sessionStorage.getItem('token') && !user.authenticated) {
  157. const token = JSON.parse(sessionStorage.getItem('token'));
  158. HTTP.defaults.headers.Authorization = 'Token ' + token.token;
  159. user.login(token);
  160. recovered = true
  161. }
  162. if (to.matched.some(record => 'guest' in record.meta && record.meta.guest === false)) {
  163. // this route requires auth, check if logged in
  164. // if not, redirect to login page.
  165. if (!user.authenticated) {
  166. next({
  167. name: 'login',
  168. query: { redirect: to.fullPath }
  169. })
  170. } else {
  171. next()
  172. }
  173. } else {
  174. if (user.authenticated) {
  175. // Log in state was present, but not needed for the current page
  176. if (recovered && to.name === 'home') {
  177. // User restored a previous session. If navigation to home, divert to home page for authorized users
  178. next({name: 'domains'})
  179. }
  180. }
  181. next() // make sure to always call next()!
  182. }
  183. });
  184. export default router