fix: remove hardcoded CORS_ORIGINS from docker-compose, improve login errors
CORS_ORIGINS was hardcoded in docker-compose.yml, silently overriding .env and breaking login for users who change the frontend port. It now comes from .env exclusively, with a clear comment in .env.example. Login page now distinguishes network errors (CORS/offline) from wrong credentials, and footer correctly references .env instead of config.yml.
This commit is contained in:
@@ -20,8 +20,9 @@ export function LoginPage() {
|
||||
try {
|
||||
const res = await authApi.login(username, password)
|
||||
login(res.data.access_token)
|
||||
} catch {
|
||||
setError('Invalid username or password')
|
||||
} catch (err: unknown) {
|
||||
const hasResponse = err && typeof err === 'object' && 'response' in err
|
||||
setError(hasResponse ? 'Invalid username or password' : 'Could not reach the server — check your CORS_ORIGINS setting')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -95,7 +96,7 @@ export function LoginPage() {
|
||||
</form>
|
||||
|
||||
<p className="text-center text-[10px] text-muted-foreground/40 mt-4">
|
||||
Credentials configured in <span className="font-mono">config.yml</span>
|
||||
Credentials configured in <span className="font-mono">.env</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('LoginPage', () => {
|
||||
})
|
||||
|
||||
it('shows a generic error message — no credential enumeration', async () => {
|
||||
vi.mocked(authApi.login).mockRejectedValue(new Error('401'))
|
||||
vi.mocked(authApi.login).mockRejectedValue({ response: { status: 401 } })
|
||||
render(<LoginPage />)
|
||||
fireEvent.change(screen.getByLabelText('Username'), { target: { value: 'admin' } })
|
||||
fireEvent.change(screen.getByLabelText('Password'), { target: { value: 'wrongpass' } })
|
||||
@@ -65,6 +65,17 @@ describe('LoginPage', () => {
|
||||
expect(errors[0].textContent).toBe('Invalid username or password')
|
||||
})
|
||||
|
||||
it('shows a network error message when no response (e.g. CORS misconfiguration)', async () => {
|
||||
vi.mocked(authApi.login).mockRejectedValue(new Error('Network Error'))
|
||||
render(<LoginPage />)
|
||||
fireEvent.change(screen.getByLabelText('Username'), { target: { value: 'admin' } })
|
||||
fireEvent.change(screen.getByLabelText('Password'), { target: { value: 'admin' } })
|
||||
fireEvent.submit(screen.getByRole('button', { name: /sign in/i }).closest('form')!)
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/Could not reach the server/)).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
it('clears previous error before each new attempt', async () => {
|
||||
vi.mocked(authApi.login)
|
||||
.mockRejectedValueOnce(new Error('401'))
|
||||
|
||||
Reference in New Issue
Block a user