From 771d75a732c093be893f4cf4d1ea367d22ea09eb Mon Sep 17 00:00:00 2001 From: Jayden Date: Tue, 23 Jul 2024 22:22:58 -0500 Subject: [PATCH] wip: fix auth --- api/backend/app.py | 25 +++++++------------------ package-lock.json | 16 ++++++++++++++++ package.json | 2 ++ src/components/JobTable.tsx | 21 ++++++++++++++------- src/contexts/AuthContext.tsx | 3 +++ src/pages/jobs.tsx | 2 +- 6 files changed, 43 insertions(+), 26 deletions(-) diff --git a/api/backend/app.py b/api/backend/app.py index d96a899..98ee479 100644 --- a/api/backend/app.py +++ b/api/backend/app.py @@ -5,12 +5,14 @@ from io import BytesIO from openpyxl import Workbook # PDM -from fastapi import BackgroundTasks, FastAPI, HTTPException +from fastapi import BackgroundTasks, Depends, FastAPI, HTTPException from fastapi.encoders import jsonable_encoder -from fastapi.responses import FileResponse, JSONResponse, StreamingResponse -from fastapi.staticfiles import StaticFiles +from fastapi.responses import JSONResponse, StreamingResponse from fastapi.middleware.cors import CORSMiddleware import docker +from api.backend.schemas import User + +from api.backend.auth.auth_utils import get_current_user client = docker.from_env() @@ -53,22 +55,9 @@ app.add_middleware( allow_headers=["*"], ) -# app.mount("/_next/static", StaticFiles(directory="./dist/_next/static"), name="static") -# app.mount("/images", StaticFiles(directory="./dist/images"), name="images") - -# @app.get("/") -# def read_root(): -# return FileResponse("./dist/index.html") - - -# @app.get("/favicon.ico") -# def read_favicon(): -# return FileResponse("dist/favicon.ico") - - -@app.post("/api/update") -async def update(update_jobs: UpdateJobs): +@app.post("/api/update", response_model=User) +async def update(update_jobs: UpdateJobs, user: User = Depends(get_current_user)): """Used to update jobs""" await update_job(update_jobs.ids, update_jobs.field, update_jobs.value) diff --git a/package-lock.json b/package-lock.json index 0fd1aec..980cba9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "chart.js": "^4.4.3", "cookie": "^0.6.0", "framer-motion": "^4.1.17", + "js-cookie": "^3.0.5", "next": "^14.2.4", "next-auth": "^4.24.7", "nookies": "^2.5.2", @@ -39,6 +40,7 @@ "web-vitals": "^2.1.4" }, "devDependencies": { + "@types/js-cookie": "^3.0.6", "tailwindcss": "^3.3.5" } }, @@ -6210,6 +6212,12 @@ "node": ">=8" } }, + "node_modules/@types/js-cookie": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.12", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", @@ -14186,6 +14194,14 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index bca88bc..ab48692 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "chart.js": "^4.4.3", "cookie": "^0.6.0", "framer-motion": "^4.1.17", + "js-cookie": "^3.0.5", "next": "^14.2.4", "next-auth": "^4.24.7", "nookies": "^2.5.2", @@ -58,6 +59,7 @@ ] }, "devDependencies": { + "@types/js-cookie": "^3.0.6", "tailwindcss": "^3.3.5" }, "overrides": { diff --git a/src/components/JobTable.tsx b/src/components/JobTable.tsx index c2e7b0a..f8cd290 100644 --- a/src/components/JobTable.tsx +++ b/src/components/JobTable.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { Dispatch, SetStateAction, useState } from "react"; import { IconButton, Box, @@ -19,10 +19,11 @@ import { useRouter } from "next/router"; import { Favorites, JobQueue } from "./jobs"; import { Job } from "../types"; import { Constants } from "../lib"; +import Cookies from "js-cookie"; interface JobTableProps { jobs: Job[]; - fetchJobs: () => void; + setJobs: React.Dispatch>; } interface ColorMap { @@ -36,13 +37,14 @@ const COLOR_MAP: ColorMap = { Failed: "rgba(214,0,25,0.25)", }; -const JobTable: React.FC = ({ jobs, fetchJobs }) => { +const JobTable: React.FC = ({ jobs, setJobs }) => { const [selectedJobs, setSelectedJobs] = useState>(new Set()); const [allSelected, setAllSelected] = useState(false); const [searchQuery, setSearchQuery] = useState(""); const [searchMode, setSearchMode] = useState("url"); const [favoriteView, setFavoriteView] = useState(false); + const token = Cookies.get("token"); const router = useRouter(); const handleDownload = async (ids: string[]) => { @@ -108,7 +110,9 @@ const JobTable: React.FC = ({ jobs, fetchJobs }) => { }); if (response.ok) { - fetchJobs(); + setJobs((jobs) => + jobs.filter((job) => !Array.from(selectedJobs).includes(job.id)) + ); setSelectedJobs(new Set()); } }; @@ -131,13 +135,16 @@ const JobTable: React.FC = ({ jobs, fetchJobs }) => { value: value, }; + console.log(`Token: ${token}`); + await fetch(`${Constants.DOMAIN}/api/update`, { method: "POST", - headers: { "Content-Type": "application/json" }, + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, body: JSON.stringify(postBody), }); - - await fetchJobs(); }; return ( diff --git a/src/contexts/AuthContext.tsx b/src/contexts/AuthContext.tsx index 46b5b87..78ea615 100644 --- a/src/contexts/AuthContext.tsx +++ b/src/contexts/AuthContext.tsx @@ -1,6 +1,7 @@ import React, { createContext, useContext, useState, useEffect } from "react"; import axios from "axios"; import { Constants } from "../lib"; +import Cookies from "js-cookie"; interface AuthContextProps { user: any; @@ -45,6 +46,7 @@ export const AuthProvider: React.FC = ({ children }) => { `${Constants.DOMAIN}/api/auth/token`, params ); + Cookies.set("token", response.data.access_token); localStorage.setItem("token", response.data.access_token); const userResponse = await axios.get( `${Constants.DOMAIN}/api/auth/users/me`, @@ -57,6 +59,7 @@ export const AuthProvider: React.FC = ({ children }) => { }; const logout = () => { + Cookies.remove("token"); localStorage.removeItem("token"); setUser(null); setIsAuthenticated(false); diff --git a/src/pages/jobs.tsx b/src/pages/jobs.tsx index 0651725..2417748 100644 --- a/src/pages/jobs.tsx +++ b/src/pages/jobs.tsx @@ -52,7 +52,7 @@ const Jobs: React.FC = ({ initialJobs, initialUser }) => { return ( <> {user ? ( - + ) : (