Dominic Elm
commited on
feat: allow to disable auth during development (#21)
Browse files
packages/bolt/README.md
CHANGED
@@ -37,10 +37,10 @@ VITE_LOG_LEVEL=debug
|
|
37 |
```
|
38 |
|
39 |
If you want to run authentication against a local StackBlitz instance, add:
|
|
|
40 |
```
|
41 |
VITE_CLIENT_ORIGIN=https://local.stackblitz.com:3000
|
42 |
```
|
43 |
-
`
|
44 |
|
45 |
**Important**: Never commit your `.env.local` file to version control. It's already included in .gitignore.
|
46 |
|
|
|
37 |
```
|
38 |
|
39 |
If you want to run authentication against a local StackBlitz instance, add:
|
40 |
+
|
41 |
```
|
42 |
VITE_CLIENT_ORIGIN=https://local.stackblitz.com:3000
|
43 |
```
|
|
|
44 |
|
45 |
**Important**: Never commit your `.env.local` file to version control. It's already included in .gitignore.
|
46 |
|
packages/bolt/app/components/chat/Chat.client.tsx
CHANGED
@@ -47,7 +47,7 @@ export function ChatImpl({ initialMessages, storeMessageHistory }: ChatProps) {
|
|
47 |
const { messages, isLoading, input, handleInputChange, setInput, handleSubmit, stop, append } = useChat({
|
48 |
api: '/api/chat',
|
49 |
onError: (error) => {
|
50 |
-
logger.error(error);
|
51 |
toast.error('There was an error processing your request');
|
52 |
},
|
53 |
onFinish: () => {
|
|
|
47 |
const { messages, isLoading, input, handleInputChange, setInput, handleSubmit, stop, append } = useChat({
|
48 |
api: '/api/chat',
|
49 |
onError: (error) => {
|
50 |
+
logger.error('Request failed\n\n', error);
|
51 |
toast.error('There was an error processing your request');
|
52 |
},
|
53 |
onFinish: () => {
|
packages/bolt/app/components/header/Header.tsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
import { ClientOnly } from 'remix-utils/client-only';
|
2 |
-
import { OpenStackBlitz } from './OpenStackBlitz.client';
|
3 |
import { IconButton } from '~/components/ui/IconButton';
|
|
|
4 |
|
5 |
export function Header() {
|
6 |
return (
|
|
|
1 |
import { ClientOnly } from 'remix-utils/client-only';
|
|
|
2 |
import { IconButton } from '~/components/ui/IconButton';
|
3 |
+
import { OpenStackBlitz } from './OpenStackBlitz.client';
|
4 |
|
5 |
export function Header() {
|
6 |
return (
|
packages/bolt/app/lib/.server/login.ts
CHANGED
@@ -1,12 +1,5 @@
|
|
1 |
-
import { env } from 'node:process';
|
2 |
-
import { isAuthenticated } from './sessions';
|
3 |
import { json, redirect, type LoaderFunctionArgs } from '@remix-run/cloudflare';
|
4 |
-
|
5 |
-
export function verifyPassword(password: string, cloudflareEnv: Env) {
|
6 |
-
const loginPassword = env.LOGIN_PASSWORD || cloudflareEnv.LOGIN_PASSWORD;
|
7 |
-
|
8 |
-
return password === loginPassword;
|
9 |
-
}
|
10 |
|
11 |
type RequestArgs = Pick<LoaderFunctionArgs, 'request' | 'context'>;
|
12 |
|
@@ -14,7 +7,7 @@ export async function handleAuthRequest<T extends RequestArgs>(args: T, body: ob
|
|
14 |
const { request, context } = args;
|
15 |
const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env);
|
16 |
|
17 |
-
if (authenticated) {
|
18 |
return json(body, response);
|
19 |
}
|
20 |
|
@@ -25,7 +18,7 @@ export async function handleWithAuth<T extends RequestArgs>(args: T, handler: (a
|
|
25 |
const { request, context } = args;
|
26 |
const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env);
|
27 |
|
28 |
-
if (authenticated) {
|
29 |
const handlerResponse = await handler(args);
|
30 |
|
31 |
if (response) {
|
|
|
|
|
|
|
1 |
import { json, redirect, type LoaderFunctionArgs } from '@remix-run/cloudflare';
|
2 |
+
import { isAuthenticated } from './sessions';
|
|
|
|
|
|
|
|
|
|
|
3 |
|
4 |
type RequestArgs = Pick<LoaderFunctionArgs, 'request' | 'context'>;
|
5 |
|
|
|
7 |
const { request, context } = args;
|
8 |
const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env);
|
9 |
|
10 |
+
if (authenticated || import.meta.env.VITE_DISABLE_AUTH) {
|
11 |
return json(body, response);
|
12 |
}
|
13 |
|
|
|
18 |
const { request, context } = args;
|
19 |
const { authenticated, response } = await isAuthenticated(request, context.cloudflare.env);
|
20 |
|
21 |
+
if (authenticated || import.meta.env.VITE_DISABLE_AUTH) {
|
22 |
const handlerResponse = await handler(args);
|
23 |
|
24 |
if (response) {
|
packages/bolt/app/lib/.server/sessions.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import { createCookieSessionStorage, redirect } from '@remix-run/cloudflare';
|
2 |
import { decodeJwt } from 'jose';
|
3 |
-
import { request as doRequest } from '~/lib/fetch';
|
4 |
import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants';
|
|
|
5 |
import { logger } from '~/utils/logger';
|
6 |
|
7 |
const DEV_SESSION_SECRET = import.meta.env.DEV ? 'LZQMrERo3Ewn/AbpSYJ9aw==' : undefined;
|
@@ -33,7 +33,7 @@ export async function isAuthenticated(request: Request, env: Env) {
|
|
33 |
try {
|
34 |
data = await refreshToken(token);
|
35 |
} catch {
|
36 |
-
// ignore
|
37 |
}
|
38 |
|
39 |
if (data != null) {
|
|
|
1 |
import { createCookieSessionStorage, redirect } from '@remix-run/cloudflare';
|
2 |
import { decodeJwt } from 'jose';
|
|
|
3 |
import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants';
|
4 |
+
import { request as doRequest } from '~/lib/fetch';
|
5 |
import { logger } from '~/utils/logger';
|
6 |
|
7 |
const DEV_SESSION_SECRET = import.meta.env.DEV ? 'LZQMrERo3Ewn/AbpSYJ9aw==' : undefined;
|
|
|
33 |
try {
|
34 |
data = await refreshToken(token);
|
35 |
} catch {
|
36 |
+
// we can ignore the error here because it's handled below
|
37 |
}
|
38 |
|
39 |
if (data != null) {
|
packages/bolt/app/routes/login.tsx
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
import {
|
2 |
json,
|
3 |
redirect,
|
|
|
4 |
type ActionFunctionArgs,
|
5 |
type LoaderFunctionArgs,
|
6 |
-
redirectDocument,
|
7 |
} from '@remix-run/cloudflare';
|
8 |
import { useFetcher, useLoaderData } from '@remix-run/react';
|
9 |
import { auth, type AuthAPI } from '@webcontainer/api';
|
10 |
import { useEffect, useState } from 'react';
|
11 |
import { createUserSession, isAuthenticated, validateAccessToken } from '~/lib/.server/sessions';
|
12 |
-
import { request as doRequest } from '~/lib/fetch';
|
13 |
import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants';
|
|
|
14 |
import { logger } from '~/utils/logger';
|
15 |
|
16 |
export async function loader({ request, context }: LoaderFunctionArgs) {
|
@@ -49,7 +49,7 @@ export async function action({ request, context }: ActionFunctionArgs) {
|
|
49 |
throw await response.json();
|
50 |
}
|
51 |
} catch (error) {
|
52 |
-
logger.warn('Authentication
|
53 |
logger.warn(error);
|
54 |
|
55 |
return json({ error: 'invalid-token' as const }, { status: 401 });
|
@@ -100,7 +100,6 @@ export default function Login() {
|
|
100 |
<div>
|
101 |
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">Login</h2>
|
102 |
</div>
|
103 |
-
|
104 |
{redirected ? 'Processing auth...' : <LoginForm />}
|
105 |
</div>
|
106 |
</div>
|
@@ -162,7 +161,6 @@ function LoginForm() {
|
|
162 |
>
|
163 |
{login?.kind === 'pending' ? 'Authenticating...' : 'Continue with StackBlitz'}
|
164 |
</button>
|
165 |
-
|
166 |
{login?.kind === 'error' && (
|
167 |
<div>
|
168 |
<h2>
|
|
|
1 |
import {
|
2 |
json,
|
3 |
redirect,
|
4 |
+
redirectDocument,
|
5 |
type ActionFunctionArgs,
|
6 |
type LoaderFunctionArgs,
|
|
|
7 |
} from '@remix-run/cloudflare';
|
8 |
import { useFetcher, useLoaderData } from '@remix-run/react';
|
9 |
import { auth, type AuthAPI } from '@webcontainer/api';
|
10 |
import { useEffect, useState } from 'react';
|
11 |
import { createUserSession, isAuthenticated, validateAccessToken } from '~/lib/.server/sessions';
|
|
|
12 |
import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants';
|
13 |
+
import { request as doRequest } from '~/lib/fetch';
|
14 |
import { logger } from '~/utils/logger';
|
15 |
|
16 |
export async function loader({ request, context }: LoaderFunctionArgs) {
|
|
|
49 |
throw await response.json();
|
50 |
}
|
51 |
} catch (error) {
|
52 |
+
logger.warn('Authentication failed');
|
53 |
logger.warn(error);
|
54 |
|
55 |
return json({ error: 'invalid-token' as const }, { status: 401 });
|
|
|
100 |
<div>
|
101 |
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">Login</h2>
|
102 |
</div>
|
|
|
103 |
{redirected ? 'Processing auth...' : <LoginForm />}
|
104 |
</div>
|
105 |
</div>
|
|
|
161 |
>
|
162 |
{login?.kind === 'pending' ? 'Authenticating...' : 'Continue with StackBlitz'}
|
163 |
</button>
|
|
|
164 |
{login?.kind === 'error' && (
|
165 |
<div>
|
166 |
<h2>
|