Emmanuel Frimpong Asante
commited on
Commit
·
04f453e
1
Parent(s):
a16b9b7
update space
Browse files- .idea/workspace.xml +10 -14
- routes/authentication.py +8 -17
.idea/workspace.xml
CHANGED
|
@@ -6,10 +6,6 @@
|
|
| 6 |
<component name="ChangeListManager">
|
| 7 |
<list default="true" id="27c9ae1a-a6fa-4472-8bcd-a7087620894b" name="Changes" comment="update space">
|
| 8 |
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
| 9 |
-
<change beforePath="$PROJECT_DIR$/app.py" beforeDir="false" afterPath="$PROJECT_DIR$/app.py" afterDir="false" />
|
| 10 |
-
<change beforePath="$PROJECT_DIR$/routes/administration.py" beforeDir="false" afterPath="$PROJECT_DIR$/routes/administration.py" afterDir="false" />
|
| 11 |
-
<change beforePath="$PROJECT_DIR$/routes/report_dashboard.py" beforeDir="false" />
|
| 12 |
-
<change beforePath="$PROJECT_DIR$/routes/todo.py" beforeDir="false" />
|
| 13 |
</list>
|
| 14 |
<option name="SHOW_DIALOG" value="false" />
|
| 15 |
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
@@ -123,15 +119,7 @@
|
|
| 123 |
<workItem from="1730305361670" duration="2425000" />
|
| 124 |
<workItem from="1730378091154" duration="2435000" />
|
| 125 |
<workItem from="1730381153348" duration="8786000" />
|
| 126 |
-
<workItem from="1730397485849" duration="
|
| 127 |
-
</task>
|
| 128 |
-
<task id="LOCAL-00030" summary="update space">
|
| 129 |
-
<option name="closed" value="true" />
|
| 130 |
-
<created>1730336863406</created>
|
| 131 |
-
<option name="number" value="00030" />
|
| 132 |
-
<option name="presentableId" value="LOCAL-00030" />
|
| 133 |
-
<option name="project" value="LOCAL" />
|
| 134 |
-
<updated>1730336863406</updated>
|
| 135 |
</task>
|
| 136 |
<task id="LOCAL-00031" summary="update space">
|
| 137 |
<option name="closed" value="true" />
|
|
@@ -517,7 +505,15 @@
|
|
| 517 |
<option name="project" value="LOCAL" />
|
| 518 |
<updated>1730402545869</updated>
|
| 519 |
</task>
|
| 520 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 521 |
<servers />
|
| 522 |
</component>
|
| 523 |
<component name="TypeScriptGeneratedFilesManager">
|
|
|
|
| 6 |
<component name="ChangeListManager">
|
| 7 |
<list default="true" id="27c9ae1a-a6fa-4472-8bcd-a7087620894b" name="Changes" comment="update space">
|
| 8 |
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
</list>
|
| 10 |
<option name="SHOW_DIALOG" value="false" />
|
| 11 |
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
|
|
| 119 |
<workItem from="1730305361670" duration="2425000" />
|
| 120 |
<workItem from="1730378091154" duration="2435000" />
|
| 121 |
<workItem from="1730381153348" duration="8786000" />
|
| 122 |
+
<workItem from="1730397485849" duration="6964000" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
</task>
|
| 124 |
<task id="LOCAL-00031" summary="update space">
|
| 125 |
<option name="closed" value="true" />
|
|
|
|
| 505 |
<option name="project" value="LOCAL" />
|
| 506 |
<updated>1730402545869</updated>
|
| 507 |
</task>
|
| 508 |
+
<task id="LOCAL-00079" summary="update space">
|
| 509 |
+
<option name="closed" value="true" />
|
| 510 |
+
<created>1730403550084</created>
|
| 511 |
+
<option name="number" value="00079" />
|
| 512 |
+
<option name="presentableId" value="LOCAL-00079" />
|
| 513 |
+
<option name="project" value="LOCAL" />
|
| 514 |
+
<updated>1730403550085</updated>
|
| 515 |
+
</task>
|
| 516 |
+
<option name="localTasksCounter" value="80" />
|
| 517 |
<servers />
|
| 518 |
</component>
|
| 519 |
<component name="TypeScriptGeneratedFilesManager">
|
routes/authentication.py
CHANGED
|
@@ -78,35 +78,31 @@ async def login_page(request: Request):
|
|
| 78 |
|
| 79 |
@auth_router.post("/login", response_model=Token)
|
| 80 |
async def login(request: Request, form_data: OAuth2PasswordRequestForm = Depends()):
|
| 81 |
-
"""Authenticate user, issue JWT, and set in a secure cookie."""
|
| 82 |
logger.info(f"User login attempt: {form_data.username}")
|
| 83 |
user = authenticate_user(form_data.username, form_data.password)
|
| 84 |
|
| 85 |
if not user:
|
| 86 |
error_message = "Invalid username or password"
|
| 87 |
logger.warning(f"Failed login attempt for user {form_data.username}: {error_message}")
|
| 88 |
-
|
| 89 |
-
return templates.TemplateResponse("auth/login.html", {
|
| 90 |
-
"request": request,
|
| 91 |
-
"error": error_message
|
| 92 |
-
})
|
| 93 |
|
|
|
|
| 94 |
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
| 95 |
access_token = create_access_token(data={"sub": user["username"]}, expires_delta=access_token_expires)
|
| 96 |
|
|
|
|
| 97 |
response = RedirectResponse(url="/admin/dashboard", status_code=status.HTTP_302_FOUND)
|
| 98 |
response.set_cookie(
|
| 99 |
key="access_token",
|
| 100 |
-
value=
|
| 101 |
httponly=True,
|
| 102 |
max_age=ACCESS_TOKEN_EXPIRE_MINUTES * 60,
|
| 103 |
secure=True,
|
| 104 |
samesite="Lax"
|
| 105 |
)
|
| 106 |
logger.info(f"User {form_data.username} logged in successfully and redirected to dashboard.")
|
| 107 |
-
log_to_db("INFO", f"User {form_data.username} logged in successfully and redirected to dashboard.")
|
| 108 |
return response
|
| 109 |
-
|
| 110 |
@auth_router.get("/me", response_model=UserResponse)
|
| 111 |
async def read_users_me(current_user: str = Depends(get_current_user)):
|
| 112 |
"""Retrieve information about the current authenticated user."""
|
|
@@ -122,14 +118,9 @@ async def read_users_me(current_user: str = Depends(get_current_user)):
|
|
| 122 |
return {"username": current_user}
|
| 123 |
|
| 124 |
@auth_router.get("/logout")
|
| 125 |
-
async def logout(request: Request
|
| 126 |
-
"""Logout the user by
|
| 127 |
-
expiration = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
| 128 |
-
blacklist_token(token, expiration)
|
| 129 |
-
|
| 130 |
response = RedirectResponse(url="/auth/login", status_code=status.HTTP_302_FOUND)
|
| 131 |
response.delete_cookie("access_token")
|
| 132 |
-
|
| 133 |
-
logger.info("User logged out and token blacklisted.")
|
| 134 |
-
log_to_db("INFO", "User logged out and token blacklisted.")
|
| 135 |
return response
|
|
|
|
| 78 |
|
| 79 |
@auth_router.post("/login", response_model=Token)
|
| 80 |
async def login(request: Request, form_data: OAuth2PasswordRequestForm = Depends()):
|
| 81 |
+
"""Authenticate user, issue JWT, and set it in a secure cookie."""
|
| 82 |
logger.info(f"User login attempt: {form_data.username}")
|
| 83 |
user = authenticate_user(form_data.username, form_data.password)
|
| 84 |
|
| 85 |
if not user:
|
| 86 |
error_message = "Invalid username or password"
|
| 87 |
logger.warning(f"Failed login attempt for user {form_data.username}: {error_message}")
|
| 88 |
+
return templates.TemplateResponse("auth/login.html", {"request": request, "error": error_message})
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
+
# Create the JWT token
|
| 91 |
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
| 92 |
access_token = create_access_token(data={"sub": user["username"]}, expires_delta=access_token_expires)
|
| 93 |
|
| 94 |
+
# Set the token in a secure cookie
|
| 95 |
response = RedirectResponse(url="/admin/dashboard", status_code=status.HTTP_302_FOUND)
|
| 96 |
response.set_cookie(
|
| 97 |
key="access_token",
|
| 98 |
+
value=access_token,
|
| 99 |
httponly=True,
|
| 100 |
max_age=ACCESS_TOKEN_EXPIRE_MINUTES * 60,
|
| 101 |
secure=True,
|
| 102 |
samesite="Lax"
|
| 103 |
)
|
| 104 |
logger.info(f"User {form_data.username} logged in successfully and redirected to dashboard.")
|
|
|
|
| 105 |
return response
|
|
|
|
| 106 |
@auth_router.get("/me", response_model=UserResponse)
|
| 107 |
async def read_users_me(current_user: str = Depends(get_current_user)):
|
| 108 |
"""Retrieve information about the current authenticated user."""
|
|
|
|
| 118 |
return {"username": current_user}
|
| 119 |
|
| 120 |
@auth_router.get("/logout")
|
| 121 |
+
async def logout(request: Request):
|
| 122 |
+
"""Logout the user by clearing the token cookie."""
|
|
|
|
|
|
|
|
|
|
| 123 |
response = RedirectResponse(url="/auth/login", status_code=status.HTTP_302_FOUND)
|
| 124 |
response.delete_cookie("access_token")
|
| 125 |
+
logger.info("User logged out successfully.")
|
|
|
|
|
|
|
| 126 |
return response
|