TimLukaHorstmann commited on
Commit
dc06740
·
1 Parent(s): 8c85576

Improved authentication for demo

Browse files
audio_ratings_db.json CHANGED
@@ -3,6 +3,10 @@
3
  "test": {
4
  "name": "test",
5
  "email": "test"
 
 
 
 
6
  }
7
  },
8
  "ratings": []
 
3
  "test": {
4
  "name": "test",
5
  "email": "test"
6
+ },
7
+ "user@example.com": {
8
+ "name": "Test User",
9
+ "email": "user@example.com"
10
  }
11
  },
12
  "ratings": []
src/app/api/config/route.ts ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { NextResponse } from 'next/server';
2
+
3
+ export async function POST(request: Request) {
4
+ try {
5
+ const { password, name, email } = await request.json();
6
+
7
+ const userPassword = process.env.USER_PASSWORD || 'demo';
8
+ const adminPassword = process.env.ADMIN_PASSWORD || 'admin';
9
+ const adminName = process.env.ADMIN_NAME || 'Admin';
10
+ const adminEmail = process.env.ADMIN_EMAIL || 'admin@example.com';
11
+
12
+ // Verify credentials first
13
+ let isValidUser = false;
14
+ let isDeveloper = false;
15
+
16
+ if (password === userPassword) {
17
+ isValidUser = true;
18
+ } else if (password === adminPassword && name === adminName && email === adminEmail) {
19
+ isValidUser = true;
20
+ isDeveloper = true;
21
+ }
22
+
23
+ if (!isValidUser) {
24
+ return NextResponse.json(
25
+ { error: 'Invalid credentials' },
26
+ { status: 401 }
27
+ );
28
+ }
29
+
30
+ // Only return what's needed for the authenticated user
31
+ return NextResponse.json({
32
+ success: true,
33
+ isDeveloper,
34
+ adminName: isDeveloper ? adminName : undefined,
35
+ adminEmail: isDeveloper ? adminEmail : undefined,
36
+ });
37
+ } catch (error) {
38
+ console.error('Error verifying credentials:', error);
39
+ return NextResponse.json(
40
+ { error: 'Authentication failed' },
41
+ { status: 500 }
42
+ );
43
+ }
44
+ }
src/app/page.tsx CHANGED
@@ -54,100 +54,76 @@ const PasswordPage = () => {
54
  const [isDeveloper, setIsDeveloper] = useState(false);
55
  const [loginError, setLoginError] = useState<string | null>(null);
56
  const {toast} = useToast();
57
- // Add this state for storing runtime config
58
  const [config, setConfig] = useState<{
59
- userPassword?: string;
60
- adminPassword?: string;
61
  adminName?: string;
62
  adminEmail?: string;
63
  }>({});
64
- const [configLoaded, setConfigLoaded] = useState(false);
65
 
66
  const passwordInputRef = useRef<HTMLInputElement>(null);
67
 
68
- // Add this effect to fetch config from API
69
- useEffect(() => {
70
- fetch('/api/config')
71
- .then(res => res.json())
72
- .then(data => {
73
- console.log('Config loaded:', {
74
- userPwd: data.userPassword ? 'Set' : 'Not set',
75
- adminPwd: data.adminPassword ? 'Set' : 'Not set',
76
- adminName: data.adminName ? 'Set' : 'Not set',
77
- adminEmail: data.adminEmail ? 'Set' : 'Not set'
78
- });
79
- setConfig(data);
80
- setConfigLoaded(true);
81
- })
82
- .catch(err => {
83
- console.error('Failed to load config:', err);
84
- // Use fallback values if config fetch fails
85
- setConfig({
86
- userPassword: process.env.USER_PASSWORD || 'demo',
87
- adminPassword: process.env.ADMIN_PASSWORD || 'admin',
88
- adminName: process.env.ADMIN_NAME || 'Admin',
89
- adminEmail: process.env.ADMIN_EMAIL || 'admin@example.com',
90
- });
91
- setConfigLoaded(true);
92
- });
93
- }, []);
94
-
95
  useEffect(() => {
96
  // Focus on the password input when the component mounts
97
  passwordInputRef.current?.focus();
98
  }, []);
99
 
100
- // Update handlePasswordSubmit to use the config
101
  const handlePasswordSubmit = async () => {
102
  try {
103
- // Use config for credentials instead of env variables
104
- const userPassword = config.userPassword || process.env.USER_PASSWORD || 'demo';
105
- const adminPassword = config.adminPassword || process.env.ADMIN_PASSWORD || 'admin';
106
- const adminName = config.adminName || process.env.ADMIN_NAME || 'Admin';
107
- const adminEmail = config.adminEmail || process.env.ADMIN_EMAIL || 'admin@example.com';
108
 
109
- // Alert for debugging
110
- toast({
111
- title: 'Debug info',
112
- description: `Checking credentials: ${userPassword?.substring(0,2)}... / ${adminPassword?.substring(0,2)}...`,
 
 
 
 
 
 
113
  });
114
-
115
- if (password === userPassword) {
116
- setIsAuthenticated(true);
117
- setIsDeveloper(false);
118
- setLoginError(null);
119
- const userInfo: UserInfo = {name, email};
120
- await saveUserInfo(email, userInfo); // Use email as userId
121
- toast({
122
- title: 'Login successful!',
123
- description: `Welcome, ${name}!`,
124
- });
125
- } else if (
126
- password === adminPassword &&
127
- name === adminName &&
128
- email === adminEmail
129
- ) {
130
  setIsAuthenticated(true);
131
- setIsDeveloper(true);
132
- setLoginError(null);
133
- toast({
134
- title: 'Developer login successful!',
135
- description: `Welcome, ${name}!`,
136
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  } else {
138
  setIsAuthenticated(false);
139
  setIsDeveloper(false);
140
- setLoginError('Incorrect credentials');
141
  toast({
142
  title: 'Login failed',
143
- description: 'Incorrect credentials.',
144
  });
145
  }
146
  } catch (error: any) {
147
- console.error('Email validation error:', error.message);
 
148
  toast({
149
  title: 'Login failed',
150
- description: 'Invalid credentials.',
151
  });
152
  }
153
  };
@@ -206,6 +182,63 @@ const PasswordPage = () => {
206
  </div>
207
  {loginError && <p className="text-red-500">{loginError}</p>}
208
  <Button onClick={handlePasswordSubmit}>Submit</Button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  </CardContent>
210
  </Card>
211
  </div>
@@ -230,8 +263,6 @@ const AudioRaterApp = ({
230
  userEmail: string;
231
  userName: string;
232
  config: { // Define the config type
233
- userPassword?: string;
234
- adminPassword?: string;
235
  adminName?: string;
236
  adminEmail?: string;
237
  };
 
54
  const [isDeveloper, setIsDeveloper] = useState(false);
55
  const [loginError, setLoginError] = useState<string | null>(null);
56
  const {toast} = useToast();
57
+ // Minimal config state for admin info only
58
  const [config, setConfig] = useState<{
 
 
59
  adminName?: string;
60
  adminEmail?: string;
61
  }>({});
 
62
 
63
  const passwordInputRef = useRef<HTMLInputElement>(null);
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  useEffect(() => {
66
  // Focus on the password input when the component mounts
67
  passwordInputRef.current?.focus();
68
  }, []);
69
 
70
+ // Update handlePasswordSubmit to authenticate via API
71
  const handlePasswordSubmit = async () => {
72
  try {
73
+ setLoginError(null);
 
 
 
 
74
 
75
+ const response = await fetch('/api/config', {
76
+ method: 'POST',
77
+ headers: {
78
+ 'Content-Type': 'application/json',
79
+ },
80
+ body: JSON.stringify({
81
+ password,
82
+ name,
83
+ email,
84
+ }),
85
  });
86
+
87
+ const data = await response.json();
88
+
89
+ if (response.ok && data.success) {
 
 
 
 
 
 
 
 
 
 
 
 
90
  setIsAuthenticated(true);
91
+ setIsDeveloper(data.isDeveloper);
92
+
93
+ if (data.isDeveloper) {
94
+ // Store admin info if user is developer
95
+ setConfig({
96
+ adminName: data.adminName,
97
+ adminEmail: data.adminEmail,
98
+ });
99
+ toast({
100
+ title: 'Developer login successful!',
101
+ description: `Welcome, ${name}!`,
102
+ });
103
+ } else {
104
+ // Regular user login
105
+ const userInfo: UserInfo = {name, email};
106
+ await saveUserInfo(email, userInfo); // Use email as userId
107
+ toast({
108
+ title: 'Login successful!',
109
+ description: `Welcome, ${name}!`,
110
+ });
111
+ }
112
  } else {
113
  setIsAuthenticated(false);
114
  setIsDeveloper(false);
115
+ setLoginError(data.error || 'Invalid credentials');
116
  toast({
117
  title: 'Login failed',
118
+ description: data.error || 'Incorrect credentials.',
119
  });
120
  }
121
  } catch (error: any) {
122
+ console.error('Authentication error:', error);
123
+ setLoginError('Authentication failed. Please try again.');
124
  toast({
125
  title: 'Login failed',
126
+ description: 'Authentication failed. Please try again.',
127
  });
128
  }
129
  };
 
182
  </div>
183
  {loginError && <p className="text-red-500">{loginError}</p>}
184
  <Button onClick={handlePasswordSubmit}>Submit</Button>
185
+
186
+ {/* Demo Credentials */}
187
+ <div className="mt-6 p-4 bg-gray-50 rounded-lg border">
188
+ <h3 className="text-sm font-semibold text-gray-700 mb-3">Demo Credentials</h3>
189
+
190
+ <div className="space-y-3">
191
+ <div className="text-xs">
192
+ <div className="flex justify-between items-center mb-1">
193
+ <span className="font-medium text-gray-600">Regular User:</span>
194
+ <Button
195
+ size="sm"
196
+ variant="outline"
197
+ className="h-6 text-xs px-2"
198
+ onClick={() => {
199
+ setName('Test User');
200
+ setEmail('user@example.com');
201
+ setPassword('demo');
202
+ }}
203
+ >
204
+ Fill Form
205
+ </Button>
206
+ </div>
207
+ <div className="font-mono text-gray-800 space-y-1">
208
+ <div>Name: <span className="bg-white px-1 rounded">Any name</span></div>
209
+ <div>Email: <span className="bg-white px-1 rounded">Any email</span></div>
210
+ <div>Password: <span className="bg-white px-1 rounded">demo</span></div>
211
+ </div>
212
+ </div>
213
+
214
+ <div className="text-xs">
215
+ <div className="flex justify-between items-center mb-1">
216
+ <span className="font-medium text-gray-600">Admin User:</span>
217
+ <Button
218
+ size="sm"
219
+ variant="outline"
220
+ className="h-6 text-xs px-2"
221
+ onClick={() => {
222
+ setName('admin');
223
+ setEmail('admin@tts.com');
224
+ setPassword('admin');
225
+ }}
226
+ >
227
+ Fill Form
228
+ </Button>
229
+ </div>
230
+ <div className="font-mono text-gray-800 space-y-1">
231
+ <div>Name: <span className="bg-white px-1 rounded">admin</span></div>
232
+ <div>Email: <span className="bg-white px-1 rounded">admin@tts.com</span></div>
233
+ <div>Password: <span className="bg-white px-1 rounded">admin</span></div>
234
+ </div>
235
+ </div>
236
+ </div>
237
+
238
+ <div className="mt-3 text-xs text-gray-500">
239
+ 💡 Admin users can export results and see additional analytics
240
+ </div>
241
+ </div>
242
  </CardContent>
243
  </Card>
244
  </div>
 
263
  userEmail: string;
264
  userName: string;
265
  config: { // Define the config type
 
 
266
  adminName?: string;
267
  adminEmail?: string;
268
  };