Skip to content

Commit

Permalink
Make Login/Logout UI functional
Browse files Browse the repository at this point in the history
  • Loading branch information
ankith26 committed Dec 5, 2024
1 parent c975161 commit 121080b
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 12 deletions.
10 changes: 10 additions & 0 deletions backend/routes/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ async def login(request: Request):
return response


@router.get("/has_login")
async def has_login(request: Request):
"""
Returns a boolean that indicates whether the current user is logged in or not.
This is needed because we are using http_only cookies so the client side cannot
actually read the cookie.
"""
return has_auth_id(request)


@router.get("/logout")
async def logout():
"""
Expand Down
1 change: 1 addition & 0 deletions backend/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def set_auth_id(response: RedirectResponse, uid: str | None):
response.set_cookie(
"Authorization",
jwt.encode({"_id": uid}, BACKEND_JWT_SECRET, algorithm="HS256"),
httponly=True,
max_age=864000, # 10 days
)
else:
Expand Down
91 changes: 91 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
"@emotion/react": "^11.13.5",
"@emotion/styled": "^11.13.5",
"@mui/material": "^5.16.9",
"@vitejs/plugin-react": "^4.3.4",
"axios": "^1.7.9",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^7.0.2",
"styled-components": "^6.1.13",
"@vitejs/plugin-react": "^4.3.4",
"vite": "^6.0.2"
},
"devDependencies": {
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/api.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import axios from 'axios';

const API_PREFIX = `${import.meta.env.VITE_BASE}api`;

const api = axios.create({
baseURL: API_PREFIX,
withCredentials: true,
maxRedirects: 0,
});

function prefix_api(str) {
return API_PREFIX + str;
}

export { api, prefix_api };
51 changes: 51 additions & 0 deletions frontend/src/components/Login.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { useState, useEffect } from 'react';
import { Button, CircularProgress, Box } from '@mui/material';
import { api, prefix_api } from '../api';

const LoginButton = () => {
const [isLoggedIn, setIsLoggedIn] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);

useEffect(() => {
const checkLoginStatus = async () => {
setLoading(true);
try {
const response = await api.get('/has_login');
setIsLoggedIn(response.data);
} catch (err) {
setError(err.message || 'An error occurred');
} finally {
setLoading(false);
}
};

checkLoginStatus();
}, []);

const handleAuthAction = async () => {
window.location.href = prefix_api(isLoggedIn ? '/logout' : '/login');
};

// UI rendering
return (
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2 }}>
{error && <p style={{ color: 'red' }}>{error}</p>}
<Button
variant="contained"
color="secondary"
onClick={handleAuthAction}
disabled={loading || isLoggedIn === null}
sx={{ marginTop: 2, minWidth: 150, size: "large" }}
>
{loading ? (
<CircularProgress size={24} sx={{ color: 'white' }} />
) : (
isLoggedIn !== null && (isLoggedIn ? 'Logout' : 'Login')
)}
</Button>
</Box>
);
};

export default LoginButton;
13 changes: 2 additions & 11 deletions frontend/src/pages/Home.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { Typography, Grid, Box, Container } from '@mui/material';
import Button from '@mui/material/Button';
import LoginButton from '../components/Login';

function Home() {
return (
Expand Down Expand Up @@ -71,16 +71,7 @@ function Home() {
</Grid>
</Grid>
</Box>
<Box textAlign="center">
<Button
variant="contained"
color="secondary"
sx={{ marginTop: 2 }}
size="large"
>
Login
</Button>
</Box>
<LoginButton />
</Container>
);
}
Expand Down

0 comments on commit 121080b

Please sign in to comment.