Skip to content

Commit

Permalink
add option to use vues history mode
Browse files Browse the repository at this point in the history
  • Loading branch information
fschade committed Feb 3, 2022
1 parent 87c94a1 commit aaaa4a9
Show file tree
Hide file tree
Showing 15 changed files with 196 additions and 113 deletions.
8 changes: 8 additions & 0 deletions changelog/unreleased/enhancement-history-mode
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Enhancement: Option to enable Vue history mode

We've added the option to use vue's history mode. All configuration is done automatically by the system.
To enable it, add a `<base src="PATH">` header tag to `index.html`, `oidc-callback.html` and `oidc-silent-redirect.html`.
Adding `<base>` is not needed for ocis.

https://github.com/owncloud/web/issues/6363
https://github.com/owncloud/web/issues/6277
6 changes: 6 additions & 0 deletions changelog/unreleased/enhancement-sidecar-mode
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Run web as oc10 sidecar

We've added the option to run web in oc10 sidecar mode.
Copy `config/config.json.sample-oc10` to `config/config.json`, run `yarn server` and then `docker compose up oc10`.

https://github.com/owncloud/web/issues/6363
2 changes: 1 addition & 1 deletion config/config.json.sample-oc10
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"theme": "https://localhost:9100/themes/owncloud/theme.json",
"version": "0.1.0",
"auth": {
"clientId": "",
"clientId": "UmCVsEIxdWmssxa6uVRRPC3txYBVN4qqxooJbsPhuuoPmHk9Pt9Oy68N4ZaKXUYy",
"url": "http://localhost:8080/index.php/apps/oauth2/api/v1/token",
"authUrl": "http://localhost:8080/index.php/apps/oauth2/authorize"
},
Expand Down
8 changes: 8 additions & 0 deletions dev/docker/oc10.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ARG OC10_IMAGE
FROM ${OC10_IMAGE}

RUN apt -qqy update \
&& apt -qqy --no-install-recommends install \
bash \
&& rm -rf /var/lib/apt/lists/* \
&& apt -qyy clean
7 changes: 7 additions & 0 deletions dev/docker/oc10.entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ then
M8W5mo3wQV3VHWYsaYpWhkr8dwa949i4GljCkedHhl7GWqmHMkxSeJgK2PcS0jt5 \
sqvPYXK94tMsEEVOYORxg8Ufesi2kC4WpJJSYb0Kj1DSAYl6u2XvJZjc3VcitjDv \
http://host.docker.internal:8080/index.php/apps/web/oidc-callback.html
occ oauth2:add-client \
web-sidecar \
UmCVsEIxdWmssxa6uVRRPC3txYBVN4qqxooJbsPhuuoPmHk9Pt9Oy68N4ZaKXUYy \
HW1fo6lbtgEERBQufBouJ4HID2QaDfngvIdc2vjDUE46qKB4JRG1YDir41LliReC \
http://localhost:9100/oidc-callback.html
occ config:system:set trusted_domains 0 --value="localhost"
occ config:system:set cors.allowed-domains 0 --value="http://localhost:9100"
fi

if [ -d /var/www/owncloud/apps/web/ ]
Expand Down
6 changes: 5 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ services:
- host.docker.internal:${DOCKER_HOST:-host-gateway}

oc10:
image: ${OC10_IMAGE:-owncloud/server:latest}
build:
dockerfile: oc10.Dockerfile
context: ./dev/docker
args:
OC10_IMAGE: ${OC10_IMAGE:-owncloud/server:latest}
container_name: web_oc10
ports:
- 8080:8080
Expand Down
13 changes: 8 additions & 5 deletions packages/web-container/oidc-callback.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<body>
<script>
window.onload = function() {
window.location.href = window.location.origin +
window.location.pathname.substr(0, window.location.pathname.length - 18) +
"index.html#/oidc-callback" + window.location.search;
}
window.onload = function () {
const base = document.querySelector('base')
const path = base ? new URL(base.href).pathname.split('/') : [...window.location.pathname.split('/').slice(0, -1), 'index.html#']
const url = new URL([...path, 'oidc-callback'].filter(Boolean).join('/'), window.location.origin)
window.location.href = url.href + window.location.search
}
</script>
</body>
</html>
13 changes: 8 additions & 5 deletions packages/web-container/oidc-silent-redirect.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<body>
<script>
window.onload = function() {
window.location.href = window.location.origin +
window.location.pathname.substr(0, window.location.pathname.length - 25) +
"index.html#/oidc-silent-redirect" + window.location.search;
}
window.onload = function () {
const base = document.querySelector('base')
const path = base ? new URL(base.href).pathname.split('/') : [...window.location.pathname.split('/').slice(0, -1), 'index.html#']
const url = new URL([...path, 'oidc-silent-redirect'].filter(Boolean).join('/'), window.location.origin)
window.location.href = url.href + window.location.search
}
</script>
</body>
</html>
1 change: 0 additions & 1 deletion packages/web-runtime/src/defaults/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { createStore } from 'vuex-extensions'
import Vuex from 'vuex'
export { default as Vue } from './vue'
export { default as DesignSystem } from 'owncloud-design-system'
export { default as Router } from '../router'

export const store = createStore(Vuex.Store, { ...Store })
export const pages = { success: App, failure: missingOrInvalidConfigPage }
Expand Down
4 changes: 3 additions & 1 deletion packages/web-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import {
translations,
supportedLanguages,
store,
Router as router,
Vue
} from './defaults'

import { router } from './router'

import {
requestConfiguration,
announceApplications,
Expand Down
187 changes: 104 additions & 83 deletions packages/web-runtime/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,66 +9,120 @@ import Account from '../pages/account.vue'

Vue.use(Router)

// type: patch
// temporary patch till we have upgraded web to the latest vue router which make this obsolete
// this takes care that routes like 'foo/bar/baz' which by default would be converted to 'foo%2Fbar%2Fbaz' stay as they are
// should immediately go away and be removed after finalizing the update
// to apply the patch to a route add meta.patchCleanPath = true to it
// to patch needs to be enabled on a route level, to do so add meta.patchCleanPath = true property to the route
const patchRouter = (router) => {
const bindMatcher = router.match.bind(router)
const cleanPath = (route) =>
[
['%2F', '/'],
['//', '/']
].reduce((path, rule) => path.replaceAll(rule[0], rule[1]), route || '')

router.match = (raw, current, redirectFrom) => {
const bindMatch = bindMatcher(raw, current, redirectFrom)

if (!get(bindMatch, 'meta.patchCleanPath', false)) {
return bindMatch
}

return {
...bindMatch,
path: cleanPath(bindMatch.path),
fullPath: cleanPath(bindMatch.fullPath)
}
}

return router
}

// just a dummy function to trick gettext tools
function $gettext(msg) {
return msg
}

const router = new Router({
// mode: 'history',
routes: [
{
path: '/login',
name: 'login',
components: {
fullscreen: LoginPage
const base = document.querySelector('base')
export const router = patchRouter(
new Router({
...(base && {
mode: 'history',
base: new URL(base.href).pathname
}),
routes: [
{
path: '/login',
name: 'login',
components: {
fullscreen: LoginPage
},
meta: { auth: false, hideHeadbar: true, title: $gettext('Login') }
},
meta: { auth: false, hideHeadbar: true, title: $gettext('Login') }
},
{
path: '/oidc-callback',
components: {
fullscreen: OidcCallbackPage
{
path: '/oidc-callback',
components: {
fullscreen: OidcCallbackPage
},
meta: { auth: false, hideHeadbar: true, title: $gettext('Oidc callback') }
},
meta: { auth: false, hideHeadbar: true, title: $gettext('Oidc callback') }
},
{
path: '/oidc-silent-redirect',
components: {
fullscreen: OidcCallbackPage
{
path: '/oidc-silent-redirect',
components: {
fullscreen: OidcCallbackPage
},
meta: { auth: false, hideHeadbar: true, title: $gettext('Oidc redirect') }
},
meta: { auth: false, hideHeadbar: true, title: $gettext('Oidc redirect') }
},
{
path: '/f/:fileId',
name: 'privateLink',
redirect: '/files/ops/resolver/private-link/:fileId',
meta: { hideHeadbar: true, title: $gettext('Private link') }
},
{
path: '/s/:token',
name: 'publicLink',
redirect: '/files/ops/resolver/public-link/:token',
meta: { auth: false, hideHeadbar: true, title: $gettext('Public link') }
},
{
path: '/access-denied',
name: 'accessDenied',
components: {
fullscreen: AccessDeniedPage
{
path: '/f/:fileId',
name: 'privateLink',
redirect: '/files/ops/resolver/private-link/:fileId',
meta: { hideHeadbar: true, title: $gettext('Private link') }
},
meta: { auth: false, hideHeadbar: true, title: $gettext('Access denied') }
},
{
path: '/account',
name: 'account',
components: {
app: Account
{
path: '/s/:token',
name: 'publicLink',
redirect: '/files/ops/resolver/public-link/:token',
meta: { auth: false, hideHeadbar: true, title: $gettext('Public link') }
},
meta: { title: $gettext('Account') }
}
]
})
{
path: '/access-denied',
name: 'accessDenied',
components: {
fullscreen: AccessDeniedPage
},
meta: { auth: false, hideHeadbar: true, title: $gettext('Access denied') }
},
{
path: '/account',
name: 'account',
components: {
app: Account
},
meta: { title: $gettext('Account') }
}
]
})
)

export const buildUrl = (pathname) => {
const baseUrl = new URL(window.location.href.split('#')[0])
if (baseUrl.pathname.endsWith('/index.html')) {
baseUrl.pathname = baseUrl.pathname.substr(0, baseUrl.pathname.length - 11)
}

if (/\.(html?)$/i.test(pathname)) {
baseUrl.pathname = base
? pathname
: [...baseUrl.pathname.split('/'), ...pathname.split('/')].filter(Boolean).join('/')
} else {
baseUrl[base ? 'pathname' : 'hash'] = router.resolve(pathname).href
}

return baseUrl.href
}

router.beforeEach(function (to, from, next) {
const store = Vue.$store
Expand Down Expand Up @@ -117,36 +171,3 @@ const isAuthRequired = (router, to) => {
}
return false
}

// type: patch
// temporary patch till we have upgraded web to the latest vue router which make this obsolete
// this takes care that routes like 'foo/bar/baz' which by default would be converted to 'foo%2Fbar%2Fbaz' stay as they are
// should immediately go away and be removed after finalizing the update
// to apply the patch to a route add meta.patchCleanPath = true to it
// to patch needs to be enabled on a route level, to do so add meta.patchCleanPath = true property to the route
const patchRouter = (router) => {
const bindMatcher = router.match.bind(router)
const cleanPath = (route) =>
[
['%2F', '/'],
['//', '/']
].reduce((path, rule) => path.replaceAll(rule[0], rule[1]), route || '')

router.match = (raw, current, redirectFrom) => {
const bindMatch = bindMatcher(raw, current, redirectFrom)

if (!get(bindMatch, 'meta.patchCleanPath', false)) {
return bindMatch
}

return {
...bindMatch,
path: cleanPath(bindMatch.path),
fullPath: cleanPath(bindMatch.fullPath)
}
}

return router
}

export default patchRouter(router)
11 changes: 4 additions & 7 deletions packages/web-runtime/src/services/auth.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import { Log, User, UserManager, WebStorageStateStore } from 'oidc-client'
import { buildUrl } from '../router'

export function initVueAuthenticate(config) {
if (config) {
const store = new WebStorageStateStore({
prefix: 'oc_oAuth',
store: sessionStorage
})
let baseUrl = window.location.href.split('#')[0]
if (baseUrl.endsWith('/index.html')) {
baseUrl = baseUrl.substr(0, baseUrl.length - 10)
}
const openIdConfig = {
userStore: store,
redirect_uri: baseUrl + 'oidc-callback.html',
redirect_uri: buildUrl('/oidc-callback.html'),
response_type: 'code', // code triggers auth code grant flow
response_mode: 'query',
scope: 'openid profile offline_access',
monitorSession: false,
// set uri directly to the login route to prevent problems with query parameters.
// See https://github.com/owncloud/web/issues/3285
post_logout_redirect_uri: baseUrl + '#/login',
silent_redirect_uri: baseUrl + 'oidc-silent-redirect.html',
post_logout_redirect_uri: buildUrl('/login'),
silent_redirect_uri: buildUrl('/oidc-silent-redirect.html'),
accessTokenExpiringNotificationTime: 10,
automaticSilentRenew: true,
filterProtocolClaims: true,
Expand Down
12 changes: 4 additions & 8 deletions packages/web-runtime/src/services/clientRegistration.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { buildUrl } from '../router'

async function get(url) {
return await fetch(url)
.then((res) => {
Expand Down Expand Up @@ -35,16 +37,10 @@ export async function registerClient(openIdConfig) {
}
}
sessionStorage.removeItem('dynamicClientData')

let baseUrl = window.location.href.split('#')[0]
if (baseUrl.endsWith('/index.html')) {
baseUrl = baseUrl.substr(0, baseUrl.length - 10)
}

const wellKnown = await get(`${openIdConfig.authority}/.well-known/openid-configuration`)
const resp = await post(wellKnown.registration_endpoint, {
redirect_uris: [baseUrl + 'oidc-callback.html'],
client_name: `ownCloud Web on ${baseUrl}`
redirect_uris: [buildUrl('/oidc-callback.html')],
client_name: `ownCloud Web on ${window.location.origin}`
})
sessionStorage.setItem('dynamicClientData', JSON.stringify(resp))
return resp
Expand Down
2 changes: 1 addition & 1 deletion packages/web-runtime/src/store/user.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import get from 'lodash-es/get.js'
import isEmpty from 'lodash-es/isEmpty'
import initVueAuthenticate from '../services/auth'
import router from '../router/'
import { router } from '../router'

let vueAuthInstance

Expand Down
Loading

0 comments on commit aaaa4a9

Please sign in to comment.