diff --git a/backend/main.py b/backend/main.py index e35c638..6769662 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,6 +1,6 @@ from fastapi import FastAPI, HTTPException, Header, Depends from fastapi.middleware.cors import CORSMiddleware -from pydantic import BaseModel +from pydantic import BaseModel, Field from typing import List, Optional from datetime import datetime from sqlalchemy.orm import Session @@ -40,8 +40,11 @@ class UserRegister(BaseModel): password: str class UserLogin(BaseModel): - email: str + username_or_email: str = Field(..., alias='usernameOrEmail') password: str + + class Config: + populate_by_name = True class AuthResponse(BaseModel): user: UserResponse @@ -172,16 +175,18 @@ def register(user_data: UserRegister, db: Session = Depends(get_db)): @app.post("/login", response_model=AuthResponse) def login(user_data: UserLogin, db: Session = Depends(get_db)): - """Login a user""" + """Login a user with username or email""" password_hash = hash_password(user_data.password) + # Try to find user by email or username user = db.query(db_models.User).filter( - db_models.User.email == user_data.email, + ((db_models.User.email == user_data.username_or_email) | + (db_models.User.username == user_data.username_or_email)), db_models.User.password_hash == password_hash ).first() if not user: - raise HTTPException(status_code=401, detail="Invalid email or password") + raise HTTPException(status_code=401, detail="Invalid credentials") # Create new token token_str = str(uuid.uuid4()) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 9f58122..274c158 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -250,7 +250,7 @@ function App() {

✓ Tasko

- {user.username} + Hello, {user.username}! diff --git a/frontend/src/Auth.jsx b/frontend/src/Auth.jsx index de0aa0c..84d2ac4 100644 --- a/frontend/src/Auth.jsx +++ b/frontend/src/Auth.jsx @@ -6,6 +6,7 @@ const API_URL = 'http://localhost:8001' function Auth({ onLogin }) { const [isLogin, setIsLogin] = useState(true) const [username, setUsername] = useState('') + const [usernameOrEmail, setUsernameOrEmail] = useState('') const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [error, setError] = useState('') @@ -16,7 +17,7 @@ function Auth({ onLogin }) { setError('') if (isLogin) { - if (!email.trim() || !password.trim()) { + if (!usernameOrEmail.trim() || !password.trim()) { setError('Please fill in all fields') return } @@ -32,7 +33,7 @@ function Auth({ onLogin }) { try { const endpoint = isLogin ? '/login' : '/register' const payload = isLogin - ? { email, password } + ? { usernameOrEmail: usernameOrEmail, password } : { username, email, password } const response = await fetch(`${API_URL}${endpoint}`, { @@ -104,16 +105,29 @@ function Auth({ onLogin }) {
)} -
- - setEmail(e.target.value)} - placeholder="Enter your email" - disabled={loading} - /> -
+ {isLogin ? ( +
+ + setUsernameOrEmail(e.target.value)} + placeholder="Enter your username or email" + disabled={loading} + /> +
+ ) : ( +
+ + setEmail(e.target.value)} + placeholder="Enter your email" + disabled={loading} + /> +
+ )}