Created
January 18, 2024 08:36
-
-
Save tabdon/d568ae78f4751c082deca08e9af5862a to your computer and use it in GitHub Desktop.
Revisions
-
tabdon created this gist
Jan 18, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,156 @@ # Django-ninja APIs (Python) from ninja import Router, Schema from django.http import JsonResponse from django.contrib.auth import authenticate, login from django.views.decorators.csrf import ensure_csrf_cookie from django.contrib.auth.models import User from ninja.errors import HttpError router = Router() _TGS = ['User API'] class UserIn(Schema): email: str password: str class UserOut(Schema): id: int email: str class LoginIn(Schema): email: str password: str @router.get("/me", tags=_TGS, response=UserOut) def get_me(request): if request.user: return request.user else: raise HttpError(401, "Need to login.") @router.post("/login", tags=_TGS, response=UserOut, auth=None) def login_user(request, payload: LoginIn): user = User(**payload.dict()) user = authenticate(request, email=user.email, password=user.password) if user is not None: login(request, user) print("login good") return user else: print("login bad") return JsonResponse({"error": "email or password is incorrect"}) @router.get('/set-cookie', tags=_TGS, auth=None) @ensure_csrf_cookie def login_set_cookie(request): """ `login_view` requires that a csrf cookie be set. `getCsrfToken` in `auth.js` uses this cookie to make a request to `login_view` """ return JsonResponse({"details": "CSRF cookie set"}) # React Component for Login import { useState } from "react"; import { useNavigate } from "react-router-dom"; import { getCSRFToken } from "../../utils/csrf"; const Login = () => { const navigate = useNavigate(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [error, setError] = useState(""); const handleLogin = async () => { try { const response = await fetch("/api/user/login", { method: "POST", headers: { "Content-Type": "application/json", 'X-CSRFToken': getCSRFToken(), }, body: JSON.stringify({ email, password }), }); if (response.ok) { const data = await response.json(); setError(''); navigate('/app/dash/'); console.log(data); } else { setError("Failed to login. Please try again."); } } catch (err) { setError("Failed to fetch. Please try again."); console.error(err); } }; return ( <div className="flex justify-center items-center h-screen bg-gray-100"> <div className="bg-white p-8 rounded-lg shadow-md w-96"> {error && <div className="text-red-500 mb-4">{error}</div>} <div className="mb-4"> <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="username"> Username </label> <input id="email" type="text" placeholder="Username" value={email} onChange={(e) => setEmail(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" /> </div> <div className="mb-4"> <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="password"> Password </label> <input id="password" type="password" placeholder="Password" value={password} onChange={(e) => setPassword(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" /> </div> <div className="flex items-center justify-between"> <button onClick={handleLogin} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" > Login </button> </div> </div> </div> ); }; export default Login; # CSRF.js utility export const getCSRFToken = () => { const cookies = document.cookie.split("; "); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].split("="); if (cookie[0] === "csrftoken") { return cookie[1]; } } return ""; };