Skip to content

Commit e9c4393

Browse files
committed
wip
1 parent 5590662 commit e9c4393

22 files changed

+1338
-1243
lines changed

src/components/EnvGroupManager.stories.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
import React from 'react';
22
import { Meta, StoryObj } from '@storybook/react';
33
import { EnvGroupManager } from './EnvGroupManager';
4-
4+
import { AuthProvider } from '@/lib/AuthContext';
55
const meta: Meta<typeof EnvGroupManager> = {
66
title: 'security/EnvGroupManager',
77
component: EnvGroupManager,
8+
decorators: [
9+
(Story) => (
10+
<AuthProvider>
11+
<Story />
12+
</AuthProvider>
13+
)
14+
],
815
parameters: {
916
layout: 'fullscreen',
1017
docs: {

src/components/EnvGroupManager.tsx

Lines changed: 16 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React, { useState, useEffect, useCallback } from 'react';
22
import { KeyRound, Shield, Eye, EyeOff, Plus, Trash2, ExternalLink, Copy, Check, Settings, ShieldCheck, Edit } from 'lucide-react';
3-
import { startRegistration, startAuthentication, WebAuthnError } from '../lib/webauthn';
43
import { DatabaseProvider, useDatabase } from '../pglite/db-context';
54
import { ParseSchema } from '@/pglite';
5+
import { useAuth } from '@/lib/AuthContext';
66

77
// Define the schema for our env group manager
88
const ENV_GROUP_MANAGER_SCHEMA = `
@@ -44,7 +44,7 @@ interface EnvVariable {
4444

4545
// Props for the component
4646
export interface EnvGroupManagerProps {
47-
initialEmail?: string;
47+
className?: string;
4848
}
4949

5050
// Environment variable form component
@@ -706,127 +706,29 @@ const EnvGroupManagerContent = () => {
706706
};
707707

708708
// Main component
709-
export function EnvGroupManager({ initialEmail = '' }: EnvGroupManagerProps) {
710-
const [email, setEmail] = useState(initialEmail);
711-
const [status, setStatus] = useState<'initial' | 'registered' | 'authenticated'>('initial');
712-
const [error, setError] = useState<string | null>(null);
713-
714-
const handleRegister = async (e: React.FormEvent) => {
715-
e.preventDefault();
716-
try {
717-
setError(null);
718-
const credential = await startRegistration(email);
719-
console.log('Registration successful:', credential);
720-
setStatus('registered');
721-
} catch (err) {
722-
setError(err instanceof WebAuthnError ? err.message : 'Registration failed');
723-
}
724-
};
725-
726-
const handleAuthenticate = async () => {
727-
try {
728-
setError(null);
729-
const assertion = await startAuthentication();
730-
console.log('Authentication successful:', assertion);
731-
setStatus('authenticated');
732-
} catch (err) {
733-
setError(err instanceof WebAuthnError ? err.message : 'Authentication failed');
734-
}
735-
};
736-
709+
export function EnvGroupManager({ className }: EnvGroupManagerProps) {
710+
const { encryptionKey } = useAuth();
737711
return (
738-
<div className="min-h-screen bg-gradient-to-br from-gray-900 to-gray-800 text-white">
712+
<div className={`min-h-screen bg-gradient-to-br from-gray-900 to-gray-800 text-white ${className || ''}`}>
739713
<div className="container mx-auto px-4 py-8">
740714
<div className="text-center mb-8">
741715
<Shield className="w-12 h-12 mx-auto mb-4 text-emerald-400" />
742716
<h1 className="text-3xl font-bold mb-2">Environment Variables Manager</h1>
743717
<p className="text-gray-400">Manage your environment variables safely</p>
744718
</div>
745719

746-
{status === 'initial' && (
747-
<div className="grid md:grid-cols-2 gap-8">
748-
{/* Register */}
749-
<div className="bg-gray-800 rounded-lg p-6">
750-
<h2 className="text-xl font-semibold mb-4">Register New Passkey</h2>
751-
<form onSubmit={handleRegister} className="space-y-6">
752-
<div>
753-
<label htmlFor="email" className="block text-sm font-medium mb-2">
754-
Email Address
755-
</label>
756-
<input
757-
type="email"
758-
id="email"
759-
value={email}
760-
onChange={(e) => setEmail(e.target.value)}
761-
className="w-full px-4 py-2 rounded-lg bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-emerald-500 text-white"
762-
placeholder="Enter your email"
763-
required
764-
/>
765-
</div>
766-
<button
767-
type="submit"
768-
className="w-full bg-emerald-500 hover:bg-emerald-600 text-white font-medium py-2 px-4 rounded-lg transition-colors flex items-center justify-center gap-2"
769-
>
770-
<KeyRound className="w-5 h-5" />
771-
Register with Passkey
772-
</button>
773-
</form>
774-
</div>
775-
776-
{/* Login */}
777-
<div className="bg-gray-800 rounded-lg p-6">
778-
<h2 className="text-xl font-semibold mb-4">Login with Passkey</h2>
779-
<p className="text-gray-400 mb-6">
780-
Already have a passkey? Login directly without registration.
781-
</p>
782-
<button
783-
onClick={handleAuthenticate}
784-
className="w-full bg-emerald-500 hover:bg-emerald-600 text-white font-medium py-2 px-4 rounded-lg transition-colors flex items-center justify-center gap-2"
785-
>
786-
<KeyRound className="w-5 h-5" />
787-
Login with Passkey
788-
</button>
789-
</div>
790-
</div>
791-
)}
792-
793-
{status === 'registered' && (
794-
<div className="max-w-md mx-auto">
795-
<div className="bg-gray-800 rounded-lg p-6 text-center">
796-
<ShieldCheck className="w-12 h-12 mx-auto mb-4 text-emerald-400" />
797-
<h2 className="text-xl font-semibold mb-2">Registration Successful!</h2>
798-
<p className="text-gray-400 mb-4">Your passkey has been created.</p>
799-
<button
800-
onClick={handleAuthenticate}
801-
className="w-full bg-emerald-500 hover:bg-emerald-600 text-white font-medium py-2 px-4 rounded-lg transition-colors flex items-center justify-center gap-2"
802-
>
803-
<KeyRound className="w-5 h-5" />
804-
Continue to Login
805-
</button>
806-
</div>
807-
</div>
808-
)}
809-
810-
{status === 'authenticated' && (
811-
<div className="w-full mx-auto">
812-
<div className="bg-gray-800 rounded-lg p-6 mb-4">
813-
<DatabaseProvider
814-
schema={ENV_GROUP_MANAGER_SCHEMA}
815-
dbName="env-group-manager"
816-
secure={true} // Enable encryption for TEXT fields
817-
debug={false}
818-
>
819-
<EnvGroupManagerContent />
820-
</DatabaseProvider>
821-
</div>
822-
</div>
823-
)}
824-
825-
{error && (
826-
<div className="mt-6 bg-red-900/50 border border-red-500 text-red-200 px-4 py-3 rounded-lg">
827-
{error}
720+
<div className="w-full mx-auto">
721+
<div className="bg-gray-800 rounded-lg p-6 mb-4">
722+
<DatabaseProvider
723+
schema={ENV_GROUP_MANAGER_SCHEMA}
724+
dbName="env-group-manager"
725+
encryptionKey={encryptionKey} // Enable encryption for TEXT fields
726+
debug={false}
727+
>
728+
<EnvGroupManagerContent />
729+
</DatabaseProvider>
828730
</div>
829-
)}
731+
</div>
830732
</div>
831733
</div>
832734
);
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import type { Meta, StoryObj } from '@storybook/react';
2+
import { KitchenSink } from './KitchenSink';
3+
import { AuthProvider } from '../lib/AuthContext';
4+
import React from 'react';
5+
6+
const meta: Meta<typeof KitchenSink> = {
7+
title: 'Pages/KitchenSink',
8+
component: KitchenSink,
9+
decorators: [
10+
(Story) => (
11+
<AuthProvider>
12+
<Story />
13+
</AuthProvider>
14+
),
15+
],
16+
parameters: {
17+
layout: 'fullscreen',
18+
docs: {
19+
description: {
20+
component: 'A comprehensive demo page showcasing various features including chat, MCP servers, environment variables, database explorer, and authentication.'
21+
}
22+
}
23+
},
24+
argTypes: {
25+
initialPage: {
26+
control: 'select',
27+
options: ['chat', 'mcp_manage', 'env_manage', 'db_explorer', 'model_config', 'auth'],
28+
description: 'The initial page to display'
29+
}
30+
}
31+
};
32+
33+
export default meta;
34+
type Story = StoryObj<typeof KitchenSink>;
35+
36+
/**
37+
* Default view showing the chat page with authenticated user
38+
*/
39+
export const Default: Story = {
40+
args: {
41+
initialPage: 'chat'
42+
}
43+
};
44+
45+
/**
46+
* MCP Server Management view with authenticated user
47+
*/
48+
export const MCPManageView: Story = {
49+
args: {
50+
initialPage: 'mcp_manage'
51+
}
52+
};
53+
54+
/**
55+
* Environment Variables Management view with authenticated user
56+
*/
57+
export const EnvManageView: Story = {
58+
args: {
59+
initialPage: 'env_manage'
60+
}
61+
};
62+
63+
/**
64+
* Database Explorer view with authenticated user
65+
*/
66+
export const DBExplorerView: Story = {
67+
args: {
68+
initialPage: 'db_explorer'
69+
}
70+
};
71+
72+
/**
73+
* Model Configuration view with authenticated user
74+
*/
75+
export const ModelConfigView: Story = {
76+
args: {
77+
initialPage: 'model_config'
78+
}
79+
};
80+
81+
/**
82+
* Authentication view showing login page for unauthenticated user
83+
*/
84+
export const AuthView: Story = {
85+
args: {
86+
initialPage: 'auth'
87+
},
88+
};

0 commit comments

Comments
 (0)