mirror of
https://github.com/stackblitz/bolt.new
synced 2024-11-27 14:32:46 +00:00
feat: allow to disable auth during development (#21)
This commit is contained in:
parent
4df1da4908
commit
58af0dea8c
@ -37,10 +37,10 @@ VITE_LOG_LEVEL=debug
|
|||||||
```
|
```
|
||||||
|
|
||||||
If you want to run authentication against a local StackBlitz instance, add:
|
If you want to run authentication against a local StackBlitz instance, add:
|
||||||
|
|
||||||
```
|
```
|
||||||
VITE_CLIENT_ORIGIN=https://local.stackblitz.com:3000
|
VITE_CLIENT_ORIGIN=https://local.stackblitz.com:3000
|
||||||
```
|
```
|
||||||
`
|
|
||||||
|
|
||||||
**Important**: Never commit your `.env.local` file to version control. It's already included in .gitignore.
|
**Important**: Never commit your `.env.local` file to version control. It's already included in .gitignore.
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ export function ChatImpl({ initialMessages, storeMessageHistory }: ChatProps) {
|
|||||||
const { messages, isLoading, input, handleInputChange, setInput, handleSubmit, stop, append } = useChat({
|
const { messages, isLoading, input, handleInputChange, setInput, handleSubmit, stop, append } = useChat({
|
||||||
api: '/api/chat',
|
api: '/api/chat',
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
logger.error(error);
|
logger.error('Request failed\n\n', error);
|
||||||
toast.error('There was an error processing your request');
|
toast.error('There was an error processing your request');
|
||||||
},
|
},
|
||||||
onFinish: () => {
|
onFinish: () => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ClientOnly } from 'remix-utils/client-only';
|
import { ClientOnly } from 'remix-utils/client-only';
|
||||||
import { OpenStackBlitz } from './OpenStackBlitz.client';
|
|
||||||
import { IconButton } from '~/components/ui/IconButton';
|
import { IconButton } from '~/components/ui/IconButton';
|
||||||
|
import { OpenStackBlitz } from './OpenStackBlitz.client';
|
||||||
|
|
||||||
export function Header() {
|
export function Header() {
|
||||||
return (
|
return (
|
||||||
|
@ -1,12 +1,5 @@
|
|||||||
import { env } from 'node:process';
|
|
||||||
import { isAuthenticated } from './sessions';
|
|
||||||
import { json, redirect, type LoaderFunctionArgs } from '@remix-run/cloudflare';
|
import { json, redirect, type LoaderFunctionArgs } from '@remix-run/cloudflare';
|
||||||
|
import { isAuthenticated } from './sessions';
|
||||||
export function verifyPassword(password: string, cloudflareEnv: Env) {
|
|
||||||
const loginPassword = env.LOGIN_PASSWORD || cloudflareEnv.LOGIN_PASSWORD;
|
|
||||||
|
|
||||||
return password === loginPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
type RequestArgs = Pick<LoaderFunctionArgs, 'request' | 'context'>;
|
type RequestArgs = Pick<LoaderFunctionArgs, 'request' | 'context'>;
|
||||||
|
|
||||||
@ -14,7 +7,7 @@ export async function handleAuthRequest<T extends RequestArgs>(args: T, body: ob
|
|||||||
const { request, context } = args;
|
const { request, context } = args;
|
||||||
const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env);
|
const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env);
|
||||||
|
|
||||||
if (authenticated) {
|
if (authenticated || import.meta.env.VITE_DISABLE_AUTH) {
|
||||||
return json(body, response);
|
return json(body, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +18,7 @@ export async function handleWithAuth<T extends RequestArgs>(args: T, handler: (a
|
|||||||
const { request, context } = args;
|
const { request, context } = args;
|
||||||
const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env);
|
const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env);
|
||||||
|
|
||||||
if (authenticated) {
|
if (authenticated || import.meta.env.VITE_DISABLE_AUTH) {
|
||||||
const handlerResponse = await handler(args);
|
const handlerResponse = await handler(args);
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createCookieSessionStorage, redirect } from '@remix-run/cloudflare';
|
import { createCookieSessionStorage, redirect } from '@remix-run/cloudflare';
|
||||||
import { decodeJwt } from 'jose';
|
import { decodeJwt } from 'jose';
|
||||||
import { request as doRequest } from '~/lib/fetch';
|
|
||||||
import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants';
|
import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants';
|
||||||
|
import { request as doRequest } from '~/lib/fetch';
|
||||||
import { logger } from '~/utils/logger';
|
import { logger } from '~/utils/logger';
|
||||||
|
|
||||||
const DEV_SESSION_SECRET = import.meta.env.DEV ? 'LZQMrERo3Ewn/AbpSYJ9aw==' : undefined;
|
const DEV_SESSION_SECRET = import.meta.env.DEV ? 'LZQMrERo3Ewn/AbpSYJ9aw==' : undefined;
|
||||||
@ -33,7 +33,7 @@ export async function isAuthenticated(request: Request, env: Env) {
|
|||||||
try {
|
try {
|
||||||
data = await refreshToken(token);
|
data = await refreshToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// we can ignore the error here because it's handled below
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
json,
|
json,
|
||||||
redirect,
|
redirect,
|
||||||
|
redirectDocument,
|
||||||
type ActionFunctionArgs,
|
type ActionFunctionArgs,
|
||||||
type LoaderFunctionArgs,
|
type LoaderFunctionArgs,
|
||||||
redirectDocument,
|
|
||||||
} from '@remix-run/cloudflare';
|
} from '@remix-run/cloudflare';
|
||||||
import { useFetcher, useLoaderData } from '@remix-run/react';
|
import { useFetcher, useLoaderData } from '@remix-run/react';
|
||||||
import { auth, type AuthAPI } from '@webcontainer/api';
|
import { auth, type AuthAPI } from '@webcontainer/api';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { createUserSession, isAuthenticated, validateAccessToken } from '~/lib/.server/sessions';
|
import { createUserSession, isAuthenticated, validateAccessToken } from '~/lib/.server/sessions';
|
||||||
import { request as doRequest } from '~/lib/fetch';
|
|
||||||
import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants';
|
import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants';
|
||||||
|
import { request as doRequest } from '~/lib/fetch';
|
||||||
import { logger } from '~/utils/logger';
|
import { logger } from '~/utils/logger';
|
||||||
|
|
||||||
export async function loader({ request, context }: LoaderFunctionArgs) {
|
export async function loader({ request, context }: LoaderFunctionArgs) {
|
||||||
@ -49,7 +49,7 @@ export async function action({ request, context }: ActionFunctionArgs) {
|
|||||||
throw await response.json();
|
throw await response.json();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.warn('Authentication failure');
|
logger.warn('Authentication failed');
|
||||||
logger.warn(error);
|
logger.warn(error);
|
||||||
|
|
||||||
return json({ error: 'invalid-token' as const }, { status: 401 });
|
return json({ error: 'invalid-token' as const }, { status: 401 });
|
||||||
@ -100,7 +100,6 @@ export default function Login() {
|
|||||||
<div>
|
<div>
|
||||||
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">Login</h2>
|
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">Login</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{redirected ? 'Processing auth...' : <LoginForm />}
|
{redirected ? 'Processing auth...' : <LoginForm />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -162,7 +161,6 @@ function LoginForm() {
|
|||||||
>
|
>
|
||||||
{login?.kind === 'pending' ? 'Authenticating...' : 'Continue with StackBlitz'}
|
{login?.kind === 'pending' ? 'Authenticating...' : 'Continue with StackBlitz'}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{login?.kind === 'error' && (
|
{login?.kind === 'error' && (
|
||||||
<div>
|
<div>
|
||||||
<h2>
|
<h2>
|
||||||
|
Loading…
Reference in New Issue
Block a user