handle better public domain for apps (#7136)
* cookelogin * cookelogin * all * all * fix * all * all * update back * all * all * cookelogin * cookelogin * Update frontend/src/lib/components/apps/editor/PublicApp.svelte Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * Update frontend/src/lib/components/apps/editor/PublicApp.svelte Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * all * all --------- Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
4302ebbb8ded39e04ebcf7aaac71847c9bebe19c
|
||||
5c9a2780bdc82f243d2539007045c34049d762a6
|
||||
@@ -75,6 +75,7 @@ fn is_public_route_whitelisted(path: &str) -> bool {
|
||||
"/api/oauth/list_logins",
|
||||
"/public/*",
|
||||
"/a/*",
|
||||
"/api/oauth/get_connect/*",
|
||||
"/Inter-Variable.woff2",
|
||||
];
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
import TextInput from './text_input/TextInput.svelte'
|
||||
import { usePromise } from '$lib/svelte5Utils.svelte'
|
||||
import { pollJobResult } from './jobs/utils'
|
||||
import { sameTopDomainOrigin } from '$lib/cookies'
|
||||
|
||||
interface Props {
|
||||
step?: number
|
||||
@@ -239,7 +240,7 @@
|
||||
function popupListener(event) {
|
||||
console.log('Received oauth popup message', event)
|
||||
let data = event.data
|
||||
if (event.origin == null || event.origin !== window.location.origin) {
|
||||
if (!sameTopDomainOrigin(event.origin, window.location.origin)) {
|
||||
console.log(
|
||||
'Received oauth popup message from different origin',
|
||||
event.origin,
|
||||
@@ -397,6 +398,7 @@
|
||||
}
|
||||
window.addEventListener('message', popupListener)
|
||||
window.addEventListener('storage', handleStorageEvent)
|
||||
console.log('opening popup', url.toString())
|
||||
window.open(url.toString(), '_blank', 'popup=true')
|
||||
step += 1
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<Button variant="default" on:click={appConnect?.back ?? (() => {})}>Back</Button>
|
||||
{/if}
|
||||
|
||||
<Button {disabled} on:click={appConnect?.next ?? (() => {})}>
|
||||
<Button variant="accent" {disabled} on:click={appConnect?.next ?? (() => {})}>
|
||||
{#if step == 2 && !manual}
|
||||
Connect
|
||||
{:else if step == 1}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import Skeleton from './common/skeleton/Skeleton.svelte'
|
||||
import Button from './common/button/Button.svelte'
|
||||
import { sameTopDomainOrigin } from '$lib/cookies'
|
||||
|
||||
interface Props {
|
||||
rd?: string | undefined
|
||||
@@ -212,8 +213,9 @@
|
||||
|
||||
function popupListener(event) {
|
||||
let data = event.data
|
||||
console.log('popupListener', data, event.origin, window.location.origin)
|
||||
if (event.origin !== window.location.origin) {
|
||||
// console.log('popupListener', data, event.origin, window.location.origin)
|
||||
if (!sameTopDomainOrigin(event.origin, window.location.origin)) {
|
||||
console.log('popupListener from different origin', event.origin, window.location.origin)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -261,7 +263,9 @@
|
||||
console.error('Could not persist redirection to local storage', e)
|
||||
}
|
||||
}
|
||||
let url = base + '/api/oauth/login/' + provider
|
||||
let url = base + '/api/oauth/login/' + provider + (popup ? '?close=true' : '')
|
||||
console.log('storeRedirect', popup, url)
|
||||
|
||||
if (popup) {
|
||||
localStorage.setItem('closeUponLogin', 'true')
|
||||
window.addEventListener('message', popupListener)
|
||||
|
||||
145
frontend/src/lib/components/apps/editor/PublicApp.svelte
Normal file
145
frontend/src/lib/components/apps/editor/PublicApp.svelte
Normal file
@@ -0,0 +1,145 @@
|
||||
<script lang="ts">
|
||||
import { User, UserRoundX } from 'lucide-svelte'
|
||||
import { enterpriseLicense, userStore } from '$lib/stores'
|
||||
import { base } from '$app/paths'
|
||||
import { page } from '$app/state'
|
||||
import Login from '$lib/components/Login.svelte'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import { Alert, Skeleton } from '$lib/components/common'
|
||||
import { WindmillIcon } from '$lib/components/icons'
|
||||
import { onMount, setContext } from 'svelte'
|
||||
import { IS_APP_PUBLIC_CONTEXT_KEY, type EditorBreakpoint } from '../types'
|
||||
import { UserService, type AppWithLastVersion, type GlobalWhoamiResponse } from '$lib/gen'
|
||||
import { urlParamsToObject } from '$lib/utils'
|
||||
import { goto } from '$app/navigation'
|
||||
import AppPreview from './AppPreview.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { writable } from 'svelte/store'
|
||||
|
||||
let {
|
||||
notExists,
|
||||
noPermission,
|
||||
jwtError,
|
||||
onLoginSuccess,
|
||||
app,
|
||||
workspace
|
||||
}: {
|
||||
notExists: boolean
|
||||
noPermission: boolean
|
||||
jwtError: boolean
|
||||
onLoginSuccess: () => void
|
||||
app: (AppWithLastVersion & { value: any }) | undefined
|
||||
workspace: string | undefined
|
||||
} = $props()
|
||||
|
||||
setContext(IS_APP_PUBLIC_CONTEXT_KEY, true)
|
||||
|
||||
const breakpoint = writable<EditorBreakpoint>('lg')
|
||||
|
||||
const darkMode =
|
||||
window.localStorage.getItem('dark-mode') ??
|
||||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
||||
|
||||
if (darkMode === 'dark') {
|
||||
document.documentElement.classList.add('dark')
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark')
|
||||
}
|
||||
|
||||
let globalUser = $state<GlobalWhoamiResponse | undefined>(undefined)
|
||||
async function loadGlobalUser() {
|
||||
try {
|
||||
globalUser = await UserService.globalWhoami()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
// const user = await fetch('/api/global/user')
|
||||
// console.log(user)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
// this is to avoid loading global user if the userStore is set at loading
|
||||
setTimeout(() => {
|
||||
if ($userStore) return
|
||||
loadGlobalUser()
|
||||
}, 2000)
|
||||
})
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="z-50 text-xs fixed bottom-1 right-2 {$enterpriseLicense && !isCloudHosted()
|
||||
? 'transition-opacity delay-1000 duration-1000 opacity-20 hover:delay-0 hover:opacity-100'
|
||||
: ''}"
|
||||
>
|
||||
<a href="https://windmill.dev" class="whitespace-nowrap text-primary inline-flex items-center"
|
||||
>Powered by <WindmillIcon /> Windmill</a
|
||||
>
|
||||
</div>
|
||||
|
||||
{#snippet userInfo(child)}
|
||||
<div class="flex gap-1 items-center"><User size={14} />{child}</div>
|
||||
{/snippet}
|
||||
|
||||
<div class="z-50 text-2xs text-primary absolute top-3 left-2"
|
||||
>{#if $userStore}
|
||||
{@render userInfo($userStore.username)}
|
||||
{:else if globalUser}
|
||||
{@render userInfo(globalUser.email)}
|
||||
{:else}<UserRoundX size={14} />{/if}
|
||||
</div>
|
||||
|
||||
{#if notExists}
|
||||
<div class="px-4 mt-20"
|
||||
><Alert type="error" title="Not found"
|
||||
>There was an error loading the app, is the url correct? <a href={base}>Go to Windmill</a>
|
||||
</Alert></div
|
||||
>
|
||||
{:else if noPermission}
|
||||
<div class="px-4 mt-20 w-full text-center font-bold text-xl"> This app requires read access </div>
|
||||
<div class="text-center mt-8 text-sm text-primary">
|
||||
{#if $userStore}You are logged in but have no read access to this app{:else if globalUser && workspace}
|
||||
You are logged in but are not a member of the workspace <span class="text-xl font-bold"
|
||||
>{workspace}</span
|
||||
> this app is part of
|
||||
{:else}You must be logged in and have read access to this app{/if}</div
|
||||
>
|
||||
<div class="px-2 mx-auto mt-20 max-w-xl w-full">
|
||||
{#if !jwtError}
|
||||
<Login {onLoginSuccess} popup rd={page.url.toString()} />
|
||||
{/if}
|
||||
</div>
|
||||
{:else if app}
|
||||
{#key app}
|
||||
<div
|
||||
class={twMerge(
|
||||
'min-h-screen h-full w-full flex',
|
||||
app?.value?.['css']?.['app']?.['viewer']?.class,
|
||||
'wm-app-viewer'
|
||||
)}
|
||||
style={app?.value?.['css']?.['app']?.['viewer']?.style}
|
||||
>
|
||||
<AppPreview
|
||||
noBackend={false}
|
||||
context={{
|
||||
email: $userStore?.email,
|
||||
name: $userStore?.name,
|
||||
groups: $userStore?.groups,
|
||||
username: $userStore?.username,
|
||||
query: urlParamsToObject(page.url.searchParams),
|
||||
hash: page.url.hash.substring(1)
|
||||
}}
|
||||
{workspace}
|
||||
summary={app.summary}
|
||||
app={app.value}
|
||||
appPath={app.path}
|
||||
{breakpoint}
|
||||
policy={app.policy}
|
||||
isEditor={false}
|
||||
replaceStateFn={(path) => goto(path)}
|
||||
gotoFn={(path, opt) => goto(path, opt)}
|
||||
/>
|
||||
</div>
|
||||
{/key}
|
||||
{:else}
|
||||
<Skeleton layout={[[4], 0.5, [50]]} />
|
||||
{/if}
|
||||
29
frontend/src/lib/cookies.ts
Normal file
29
frontend/src/lib/cookies.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Reads the value of a cookie by name.
|
||||
* @param {string} name - The name of the cookie to retrieve.
|
||||
* @returns {string | undefined} The cookie value, or undefined if not found.
|
||||
*/
|
||||
export function getCookie(name: string): string | undefined {
|
||||
const match = document.cookie.match(
|
||||
new RegExp('(?:^|; )' + name.replace(/([.$?*|{}()\[\]\\\/\+^])/g, '\\$1') + '=([^;]*)')
|
||||
)
|
||||
return match ? decodeURIComponent(match[1]) : undefined
|
||||
}
|
||||
|
||||
|
||||
|
||||
// this only check the last 2 segments to work for popup on shared top-domain
|
||||
export function sameTopDomainOrigin(origin: string | null, desktopOrigin: string): boolean {
|
||||
if (origin == null) {
|
||||
return false
|
||||
}
|
||||
const getLastTwoSegments = (url: string) => {
|
||||
const parts = url.split('.');
|
||||
return parts.length >= 2 ? parts.slice(-2).join('.') : url;
|
||||
};
|
||||
if (origin.includes('.') && desktopOrigin.includes('.')) {
|
||||
return getLastTwoSegments(origin) === getLastTwoSegments(desktopOrigin);
|
||||
} else {
|
||||
return origin === desktopOrigin;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { BROWSER } from 'esm-env'
|
||||
import { base } from '$lib/base'
|
||||
import AppPreview from '$lib/components/apps/editor/AppPreview.svelte'
|
||||
import { IS_APP_PUBLIC_CONTEXT_KEY, type EditorBreakpoint } from '$lib/components/apps/types'
|
||||
|
||||
import { Alert, Skeleton } from '$lib/components/common'
|
||||
import { WindmillIcon } from '$lib/components/icons'
|
||||
import { AppService, OpenAPI, type AppWithLastVersion } from '$lib/gen'
|
||||
import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
|
||||
import { setContext } from 'svelte'
|
||||
import { writable } from 'svelte/store'
|
||||
import { setLicense } from '$lib/enterpriseUtils'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import Login from '$lib/components/Login.svelte'
|
||||
|
||||
import { getUserExt } from '$lib/user'
|
||||
import { User, UserRoundX } from 'lucide-svelte'
|
||||
import { goto } from '$app/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { page } from '$app/state'
|
||||
import { urlParamsToObject } from '$lib/utils'
|
||||
import PublicApp from '$lib/components/apps/editor/PublicApp.svelte'
|
||||
|
||||
let app: (AppWithLastVersion & { value: any }) | undefined = $state(undefined)
|
||||
let notExists = $state(false)
|
||||
let noPermission = $state(false)
|
||||
|
||||
let jwtError = $state(false)
|
||||
setContext(IS_APP_PUBLIC_CONTEXT_KEY, true)
|
||||
|
||||
function isJwt(t: string) {
|
||||
// simply check that the first part is a valid base64 encoded json
|
||||
@@ -56,9 +44,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
const parsedCustomPath = parseCustomPath(page.params.path ?? '')
|
||||
|
||||
let workspace: string | undefined = $state(undefined)
|
||||
async function loadApp() {
|
||||
const parsedCustomPath = parseCustomPath(page.params.path ?? '')
|
||||
|
||||
if (parsedCustomPath.jwt) {
|
||||
const token = 'jwt_ext_' + parsedCustomPath.jwt
|
||||
OpenAPI.TOKEN = token
|
||||
@@ -69,6 +58,7 @@
|
||||
app = await AppService.getPublicAppByCustomPath({
|
||||
customPath: parsedCustomPath.path
|
||||
})
|
||||
workspace = app.workspace_id
|
||||
workspaceStore.set(app.workspace_id)
|
||||
noPermission = false
|
||||
notExists = false
|
||||
@@ -95,93 +85,15 @@
|
||||
setLicense()
|
||||
loadApp()
|
||||
}
|
||||
|
||||
const breakpoint = writable<EditorBreakpoint>('lg')
|
||||
|
||||
const darkMode =
|
||||
window.localStorage.getItem('dark-mode') ??
|
||||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
||||
|
||||
if (darkMode === 'dark') {
|
||||
document.documentElement.classList.add('dark')
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark')
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="z-50 text-xs fixed bottom-1 right-2 {$enterpriseLicense && !isCloudHosted()
|
||||
? 'transition-opacity delay-1000 duration-1000 opacity-20 hover:delay-0 hover:opacity-100'
|
||||
: ''}"
|
||||
>
|
||||
<a href="https://windmill.dev" class="whitespace-nowrap text-primary inline-flex items-center"
|
||||
>Powered by <WindmillIcon /> Windmill</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="z-50 text-2xs text-primary absolute top-3 left-2"
|
||||
>{#if $userStore}
|
||||
<div class="flex gap-1 items-center"><User size={14} />{$userStore.username}</div>
|
||||
{:else}<UserRoundX size={14} />{/if}
|
||||
</div>
|
||||
|
||||
{#if notExists}
|
||||
<div class="px-4 mt-20"
|
||||
><Alert type="error" title="Not found"
|
||||
>There was an error loading the app, is the url correct? <a href={base}>Go to Windmill</a>
|
||||
</Alert></div
|
||||
>
|
||||
{:else if noPermission}
|
||||
<div class="px-4 mt-20 w-full text-center font-bold text-xl"
|
||||
>{#if $userStore}You are logged in but have no read access to this app{:else}You must be logged
|
||||
in and have read access to this app{/if}</div
|
||||
>
|
||||
<div class="px-2 mx-auto mt-20 max-w-xl w-full">
|
||||
{#if !jwtError}
|
||||
<Login
|
||||
onLoginSuccess={() => {
|
||||
|
||||
// window.location.reload()
|
||||
loadApp()
|
||||
app = app
|
||||
}}
|
||||
popup
|
||||
rd={page.url.toString()}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if app}
|
||||
{#key app}
|
||||
<div
|
||||
class={twMerge(
|
||||
'min-h-screen h-full w-full flex',
|
||||
app?.value?.['css']?.['app']?.['viewer']?.class,
|
||||
'wm-app-viewer'
|
||||
)}
|
||||
style={app?.value?.['css']?.['app']?.['viewer']?.style}
|
||||
>
|
||||
<AppPreview
|
||||
noBackend={false}
|
||||
context={{
|
||||
email: $userStore?.email,
|
||||
name: $userStore?.name,
|
||||
groups: $userStore?.groups,
|
||||
username: $userStore?.username,
|
||||
query: urlParamsToObject(page.url.searchParams),
|
||||
hash: page.url.hash.substring(1)
|
||||
}}
|
||||
workspace={page.params.workspace}
|
||||
summary={app.summary}
|
||||
app={app.value}
|
||||
appPath={app.path}
|
||||
{breakpoint}
|
||||
policy={app.policy}
|
||||
isEditor={false}
|
||||
replaceStateFn={(path) => goto(path)}
|
||||
gotoFn={(path, opt) => goto(path, opt)}
|
||||
/>
|
||||
</div>
|
||||
{/key}
|
||||
{:else}
|
||||
<Skeleton layout={[[4], 0.5, [50]]} />
|
||||
{/if}
|
||||
<PublicApp
|
||||
{workspace}
|
||||
{notExists}
|
||||
{noPermission}
|
||||
{jwtError}
|
||||
{app}
|
||||
onLoginSuccess={() => {
|
||||
loadApp()
|
||||
}}
|
||||
></PublicApp>
|
||||
|
||||
@@ -1,34 +1,22 @@
|
||||
<script lang="ts">
|
||||
import { BROWSER } from 'esm-env'
|
||||
import { base } from '$lib/base'
|
||||
import AppPreview from '$lib/components/apps/editor/AppPreview.svelte'
|
||||
import { IS_APP_PUBLIC_CONTEXT_KEY, type EditorBreakpoint } from '$lib/components/apps/types'
|
||||
|
||||
import { WindmillIcon } from '$lib/components/icons'
|
||||
import { AppService, OpenAPI, type AppWithLastVersion } from '$lib/gen'
|
||||
import { enterpriseLicense, userStore } from '$lib/stores'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { userStore } from '$lib/stores'
|
||||
|
||||
import { setContext } from 'svelte'
|
||||
import { writable } from 'svelte/store'
|
||||
import { setLicense } from '$lib/enterpriseUtils'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import Login from '$lib/components/Login.svelte'
|
||||
|
||||
import { getUserExt } from '$lib/user'
|
||||
import { User, UserRoundX } from 'lucide-svelte'
|
||||
import { goto } from '$app/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import Alert from '$lib/components/common/alert/Alert.svelte'
|
||||
import Skeleton from '$lib/components/common/skeleton/Skeleton.svelte'
|
||||
import { page } from '$app/state'
|
||||
import { urlParamsToObject } from '$lib/utils'
|
||||
import PublicApp from '$lib/components/apps/editor/PublicApp.svelte'
|
||||
|
||||
let app: (AppWithLastVersion & { value: any }) | undefined = $state(undefined)
|
||||
let notExists = $state(false)
|
||||
let noPermission = $state(false)
|
||||
|
||||
let jwtError = $state(false)
|
||||
setContext(IS_APP_PUBLIC_CONTEXT_KEY, true)
|
||||
|
||||
function parseSecret(secret: string): { secret: string; jwt: string } {
|
||||
const parts = secret.split('/')
|
||||
@@ -59,6 +47,11 @@
|
||||
|
||||
if (BROWSER) {
|
||||
setLicense()
|
||||
loadAll()
|
||||
}
|
||||
|
||||
function loadAll() {
|
||||
console.log('loadAll')
|
||||
loadUser().then(() => {
|
||||
loadApp()
|
||||
})
|
||||
@@ -81,95 +74,15 @@
|
||||
console.warn('Anonymous user')
|
||||
}
|
||||
}
|
||||
|
||||
const breakpoint = writable<EditorBreakpoint>('lg')
|
||||
|
||||
const darkMode =
|
||||
window.localStorage.getItem('dark-mode') ??
|
||||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
||||
|
||||
if (darkMode === 'dark') {
|
||||
document.documentElement.classList.add('dark')
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark')
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="z-50 text-xs fixed bottom-1 right-2 {$enterpriseLicense && !isCloudHosted()
|
||||
? 'transition-opacity delay-1000 duration-1000 opacity-20 hover:delay-0 hover:opacity-100'
|
||||
: ''}"
|
||||
>
|
||||
<a href="https://windmill.dev" class="whitespace-nowrap text-primary inline-flex items-center"
|
||||
>Powered by <WindmillIcon /> Windmill</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="z-50 text-2xs text-primary absolute top-3 left-2"
|
||||
>{#if $userStore}
|
||||
<div class="flex gap-1 items-center"><User size={14} />{$userStore.username}</div>
|
||||
{:else}<UserRoundX size={14} />{/if}
|
||||
</div>
|
||||
|
||||
{#if notExists}
|
||||
<div class="px-4 mt-20"
|
||||
><Alert type="error" title="Not found"
|
||||
>There was an error loading the app, is the url correct? <a href={base}>Go to Windmill</a>
|
||||
</Alert></div
|
||||
>
|
||||
{:else if noPermission}
|
||||
<div class="px-4 mt-20 w-full text-center font-bold text-xl"
|
||||
>{#if $userStore}You are logged in but have no read access to this app{:else}You must be logged
|
||||
in and have read access to this app{/if}</div
|
||||
>
|
||||
<div class="px-2 mx-auto mt-20 max-w-xl w-full">
|
||||
{#if !jwtError}
|
||||
<Login
|
||||
onLoginSuccess={() => {
|
||||
console.log('login')
|
||||
// window.location.reload()
|
||||
loadUser().then(() => {
|
||||
loadApp()
|
||||
})
|
||||
app = app
|
||||
}}
|
||||
popup
|
||||
rd={page.url.toString()}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if app}
|
||||
{#key app}
|
||||
<div
|
||||
class={twMerge(
|
||||
'min-h-screen h-full w-full flex',
|
||||
app?.value?.['css']?.['app']?.['viewer']?.class,
|
||||
'wm-app-viewer'
|
||||
)}
|
||||
style={app?.value?.['css']?.['app']?.['viewer']?.style}
|
||||
>
|
||||
<AppPreview
|
||||
noBackend={false}
|
||||
context={{
|
||||
email: $userStore?.email,
|
||||
name: $userStore?.name,
|
||||
groups: $userStore?.groups,
|
||||
username: $userStore?.username,
|
||||
query: urlParamsToObject(page.url.searchParams),
|
||||
hash: page.url.hash.substring(1)
|
||||
}}
|
||||
workspace={page.params.workspace}
|
||||
summary={app.summary}
|
||||
app={app.value}
|
||||
appPath={app.path}
|
||||
{breakpoint}
|
||||
policy={app.policy}
|
||||
isEditor={false}
|
||||
replaceStateFn={(path) => goto(path)}
|
||||
gotoFn={(path, opt) => goto(path, opt)}
|
||||
/>
|
||||
</div>
|
||||
{/key}
|
||||
{:else}
|
||||
<Skeleton layout={[[4], 0.5, [50]]} />
|
||||
{/if}
|
||||
<PublicApp
|
||||
{app}
|
||||
workspace={page.params.workspace}
|
||||
{notExists}
|
||||
{noPermission}
|
||||
{jwtError}
|
||||
onLoginSuccess={() => {
|
||||
loadAll()
|
||||
}}
|
||||
></PublicApp>
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
import { parseQueryParams } from '$lib/utils'
|
||||
import { page } from '$app/state'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import { getCookie } from '$lib/cookies'
|
||||
// import { getAndDeleteCookie } from '$lib/cookies'
|
||||
|
||||
let error = page.url.searchParams.get('error')
|
||||
let clientName = page.params.client_name ?? ''
|
||||
@@ -19,11 +21,14 @@
|
||||
let state = page.url.searchParams.get('state') ?? undefined
|
||||
|
||||
onMount(async () => {
|
||||
// const closeCookie = getAndDeleteCookie('close')
|
||||
// console.log('closeCookie', closeCookie)
|
||||
const rd = localStorage.getItem('rd')
|
||||
if (rd) {
|
||||
localStorage.removeItem('rd')
|
||||
}
|
||||
const closeUponLogin = localStorage.getItem('closeUponLogin') == 'true'
|
||||
const cookieCloseUponLogin = getCookie('close') == 'true'
|
||||
const closeUponLogin = cookieCloseUponLogin ?? localStorage.getItem('closeUponLogin') == 'true'
|
||||
if (error) {
|
||||
sendUserToast(`Error trying to login with ${clientName} ${error}`, true)
|
||||
if (closeUponLogin) {
|
||||
|
||||
@@ -11,7 +11,15 @@ const version = JSON.parse(json)
|
||||
const config = {
|
||||
server: {
|
||||
https: process.env.HTTPS === 'true',
|
||||
allowedHosts: ['localhost', '127.0.0.1', '0.0.0.0', 'rubendev.wimill.xyz', 'windmill.xyz'],
|
||||
allowedHosts: [
|
||||
'localhost',
|
||||
'127.0.0.1',
|
||||
'0.0.0.0',
|
||||
'rubendev.wimill.xyz',
|
||||
'windmill.xyz',
|
||||
'app.windmill.xyz',
|
||||
'public.windmill.xyz'
|
||||
],
|
||||
port: 3000,
|
||||
proxy: {
|
||||
'^/api/w/[^/]+/s3_proxy/.*': {
|
||||
@@ -28,8 +36,8 @@ const config = {
|
||||
},
|
||||
'^/api/.*': {
|
||||
target: process.env.REMOTE ?? 'https://app.windmill.dev/',
|
||||
changeOrigin: true,
|
||||
cookieDomainRewrite: 'localhost'
|
||||
changeOrigin: true
|
||||
// cookieDomainRewrite: 'localhost'
|
||||
},
|
||||
'^/ws/.*': {
|
||||
target: process.env.REMOTE_LSP ?? 'https://app.windmill.dev',
|
||||
@@ -64,7 +72,7 @@ const config = {
|
||||
exclude: [
|
||||
'@codingame/monaco-vscode-standalone-typescript-language-features',
|
||||
'@codingame/monaco-vscode-standalone-languages'
|
||||
],
|
||||
]
|
||||
},
|
||||
worker: {
|
||||
format: 'es'
|
||||
|
||||
Reference in New Issue
Block a user