diff --git a/src/mainPage/index.ts b/src/mainPage/index.ts index 8c8b5345..15cf9f9b 100644 --- a/src/mainPage/index.ts +++ b/src/mainPage/index.ts @@ -4,16 +4,52 @@ */ import { LiveStore, NamedNode } from 'rdflib' +import { authSession, authn } from 'solid-logic' import { getOutliner } from '../index' import { createHeader } from './header' import { createFooter } from './footer' export default async function initMainPage (store: LiveStore, uri?: string | NamedNode | null) { const outliner = getOutliner(document) - uri = uri || window.location.href - let subject = uri - if (typeof uri === 'string') subject = store.sym(uri) - outliner.GotoSubject(subject, true, undefined, true, undefined) + const hasExplicitUriArg = uri !== undefined && uri !== null + const locationUrl = new URL(window.location.href) + const explicitUriQuery = locationUrl.searchParams.get('uri') + const isLoggedIn = !!(authSession.info && authSession.info.isLoggedIn) + const isBareAppRoot = locationUrl.pathname === '/' && !locationUrl.search && !locationUrl.hash + + if (isBareAppRoot && !hasExplicitUriArg && !explicitUriQuery) { + // At bare app root, avoid fetching '/' as data. If logged in, land on the user's profile instead. + let me = authn.currentUser() + if (isLoggedIn && !me) { + let webId = await authn.checkUser() + if (!webId) { + // Some IdP/session states resolve slightly after app bootstrap. + await new Promise(resolve => setTimeout(resolve, 300)) + webId = await authn.checkUser() + } + if (typeof webId === 'string') { + me = store.sym(webId) + } + } + if (isLoggedIn && me) { + outliner.GotoSubject(me, true, undefined, true, undefined) + } else if (isLoggedIn) { + // Optional override: set localStorage.solidosSafeLandingUri to a public resource URI. + const configuredLandingUri = window.localStorage.getItem('solidosSafeLandingUri') + if (configuredLandingUri) { + const fallbackUrl = new URL(configuredLandingUri, locationUrl.origin) + if (!(fallbackUrl.origin === locationUrl.origin && fallbackUrl.pathname === '/')) { + outliner.GotoSubject(store.sym(fallbackUrl.toString()), true, undefined, true, undefined) + } + } + } + } else { + uri = uri || window.location.href + let subject = uri + if (typeof uri === 'string') subject = store.sym(uri) + outliner.GotoSubject(subject, true, undefined, true, undefined) + } + const header = await createHeader(store, outliner) const footer = createFooter(store) return Promise.all([header, footer]) diff --git a/src/outline/manager.js b/src/outline/manager.js index 767a832e..6a9031ad 100644 --- a/src/outline/manager.js +++ b/src/outline/manager.js @@ -2106,11 +2106,16 @@ export default function (context) { const existing = p.querySelector('[data-outline-error-for="' + docUri + '"]') if (existing) return } + const detailStr = typeof detail === 'string' ? detail : (detail && detail.message) || '' + const errorStatus = (errObj && errObj.status) || (detailStr.match(/status:\s*(\d+)/) || [])[1] + const isAuthError = errorStatus === 401 || errorStatus === 403 || + errorStatus === '401' || errorStatus === '403' || + /Unauthorized|Forbidden/.test(detailStr) const message = UI.widgets.errorMessageBlock( dom, - detail, - '#fee', - errObj instanceof Error ? errObj : undefined + isAuthError ? 'You need to log in to see this resource.' : detail, + isAuthError ? '#d8d8d8' : '#fee', + !isAuthError && errObj instanceof Error ? errObj : undefined ) if (docUri) message.setAttribute('data-outline-error-for', docUri) p.appendChild(message)