diff --git a/backend/app/auth.py b/backend/app/auth.py index 15905e0..4fbe17b 100644 --- a/backend/app/auth.py +++ b/backend/app/auth.py @@ -13,7 +13,7 @@ from .config import settings SECRET_KEY = settings.secret_key ALGORITHM = "HS256" -ACCESS_TOKEN_EXPIRE_MINUTES = settings.access_token_expire_minuted +ACCESS_TOKEN_EXPIRE_MINUTES = 60 pwd_context = CryptContext(schemes=["bcrypt_sha256"], deprecated="auto") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/token") diff --git a/backend/app/config.py b/backend/app/config.py index e530c49..17bf487 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -14,8 +14,6 @@ class Settings(BaseModel): secret_key: str = os.getenv("SECRET_KEY", "CHANGE_ME") - access_token_expire_minuted: int = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "60")) - @property def database_url(self): return ( diff --git a/backend/app/main.py b/backend/app/main.py index d5b64ec..4159e8d 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -10,24 +10,12 @@ from .auth import ( create_access_token, get_password_hash, ) from fastapi.security import OAuth2PasswordRequestForm -from fastapi.middleware.cors import CORSMiddleware app = FastAPI(title="Server Worklog") -app.add_middleware( - CORSMiddleware, - allow_origins=["*"], # oder deine echte Domain - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) # Nur für lokale Entwicklung, in Produktion via Alembic Base.metadata.create_all(bind=engine) -@app.options("/{path:path}") -def preflight_handler(path: str): - return {} - @app.post("/auth/register", response_model=schemas.UserRead) def register_user(user_in: schemas.UserCreate, db: Session = Depends(get_db)): existing = db.query(models.User).filter(models.User.username == user_in.username).first() @@ -98,25 +86,6 @@ def create_server( db.refresh(server) return server -@app.put("/servers/{server_id}", response_model=schemas.ServerRead) -def update_server( - server_id: int, - server: schemas.ServerUpdate, - db: Session = Depends(get_db), - user=Depends(get_current_user), -): - db_server = db.query(models.Server).filter(models.Server.id == server_id).first() - if not db_server: - raise HTTPException(status_code=404, detail="Server not found") - - db_server.hostname = server.hostname - db_server.description = server.description - db_server.owner_id = server.owner_id - - db.commit() - db.refresh(db_server) - return db_server - @app.get("/servers", response_model=List[schemas.ServerRead]) def list_servers( db: Session = Depends(get_db), diff --git a/backend/app/schemas.py b/backend/app/schemas.py index 2d88580..ec80298 100644 --- a/backend/app/schemas.py +++ b/backend/app/schemas.py @@ -21,9 +21,6 @@ class ServerBase(BaseModel): class ServerCreate(ServerBase): pass -class ServerUpdate(ServerBase): - pass - class ServerRead(ServerBase): id: int owner: OwnerRead | None = None diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index 4a7f73a..0000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Nuxt dev/build outputs -.output -.data -.nuxt -.nitro -.cache -dist - -# Node dependencies -node_modules - -# Logs -logs -*.log - -# Misc -.DS_Store -.fleet -.idea - -# Local env files -.env -.env.* -!.env.example diff --git a/frontend/README.md b/frontend/README.md deleted file mode 100644 index 25b5821..0000000 --- a/frontend/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# Nuxt Minimal Starter - -Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more. - -## Setup - -Make sure to install dependencies: - -```bash -# npm -npm install - -# pnpm -pnpm install - -# yarn -yarn install - -# bun -bun install -``` - -## Development Server - -Start the development server on `http://localhost:3000`: - -```bash -# npm -npm run dev - -# pnpm -pnpm dev - -# yarn -yarn dev - -# bun -bun run dev -``` - -## Production - -Build the application for production: - -```bash -# npm -npm run build - -# pnpm -pnpm build - -# yarn -yarn build - -# bun -bun run build -``` - -Locally preview production build: - -```bash -# npm -npm run preview - -# pnpm -pnpm preview - -# yarn -yarn preview - -# bun -bun run preview -``` - -Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information. diff --git a/frontend/app/app.vue b/frontend/app/app.vue deleted file mode 100644 index 54b6347..0000000 --- a/frontend/app/app.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - - diff --git a/frontend/app/assets/css/tailwind.css b/frontend/app/assets/css/tailwind.css deleted file mode 100644 index a90f074..0000000 --- a/frontend/app/assets/css/tailwind.css +++ /dev/null @@ -1,4 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - diff --git a/frontend/app/composables/useAPI.ts b/frontend/app/composables/useAPI.ts deleted file mode 100644 index cb93681..0000000 --- a/frontend/app/composables/useAPI.ts +++ /dev/null @@ -1,59 +0,0 @@ -export function useApi() { - const config = useRuntimeConfig() - const { token, logout } = useAuth() - - async function apiFetch(url: string, options: any = {}) { - try { - return await $fetch(url, { - baseURL: config.public.apiBase, - headers: { - ...(options.headers || {}), - ...(token.value ? { Authorization: `Bearer ${token.value}` } : {}) - }, - ...options - }) - } catch (error: any) { - // Netzwerkfehler oder Server nicht erreichbar - if (!error.response) { - console.error("API unreachable:", error) - throw new Error("Der Server ist nicht erreichbar.") - } - - const status = error.response.status - const data = error.response._data - - // 401 → Token ungültig oder abgelaufen - if (status === 401) { - console.warn("API returned 401 — logging out") - logout() - return { unauthorized: true } - } - - // 403 → keine Berechtigung - if (status === 403) { - throw new Error("Du hast keine Berechtigung für diese Aktion.") - } - - // 400 → Validierungsfehler - if (status === 400) { - throw new Error(data?.detail || "Ungültige Eingabe.") - } - - // 404 → nicht gefunden - if (status === 404) { - throw new Error("Die angeforderte Ressource wurde nicht gefunden.") - } - - // 500 → Serverfehler - if (status >= 500) { - console.error("Server error:", data) - throw new Error("Interner Serverfehler. Bitte später erneut versuchen.") - } - - // Fallback - throw new Error(data?.detail || "Unbekannter Fehler.") - } - } - - return { apiFetch } -} diff --git a/frontend/app/composables/useAuth.ts b/frontend/app/composables/useAuth.ts deleted file mode 100644 index 15e3cd2..0000000 --- a/frontend/app/composables/useAuth.ts +++ /dev/null @@ -1,46 +0,0 @@ -function decodeJwt(token: string) { - try { - const payload = token.split(".")[1] - const decoded = JSON.parse(atob(payload)) - return decoded - } catch { - return null - } -} -export function useAuth() { - const token = useState("token", () => null) - - function setToken(t: string) { - token.value = t - - if (typeof window !== "undefined") { - localStorage.setItem("token", t) - } - } - - function loadToken() { - if (typeof window !== "undefined") { - const stored = localStorage.getItem("token") - if (!stored) return - - const payload = decodeJwt(stored) - if( !payload || !payload.exp || payload.exp * 1000 < Date.now()) { - console.info("Token expired - removing it from storage") - localStorage.removeItem("token") - token.value = null - } - token.value = stored - - } - } - - function logout() { - token.value = null - - if (typeof window !== "undefined") { - localStorage.removeItem("token") - } - } - - return { token, setToken, loadToken, logout } -} diff --git a/frontend/app/composables/useOwners.ts b/frontend/app/composables/useOwners.ts deleted file mode 100644 index 6af05a0..0000000 --- a/frontend/app/composables/useOwners.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ref } from "vue" -import { isUnauthorized } from "~/utils/auth" - -export function useOwners() { - const owners = ref([]) - const loading = ref(false) - const error = ref("") - - const { apiFetch } = useApi() - - async function loadOwners() { - loading.value = true - error.value = "" - - const result = await apiFetch("/owners") - - if (isUnauthorized(result)) { - loading.value = false - return result - } - - owners.value = result - loading.value = false - return result - } - - return { - owners, - loading, - error, - loadOwners - } -} diff --git a/frontend/app/composables/useServers.ts b/frontend/app/composables/useServers.ts deleted file mode 100644 index d6bc3cc..0000000 --- a/frontend/app/composables/useServers.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { ref } from "vue" -import { isUnauthorized } from "~/utils/auth" - -export function useServers() { - const servers = ref([]) - const loading = ref(false) - const error = ref("") - - const { apiFetch } = useApi() - - async function loadServers() { - loading.value = true - error.value = "" - - const result = await apiFetch("/servers") - - if (isUnauthorized(result)) { - loading.value = false - return result - } - - servers.value = result - loading.value = false - return result - } - - async function createServer(hostname: string, description: string, owner_id: number | null) { - const payload = { - hostname: hostname, - description: description, - owner_id: owner_id - } - loading.value = true - error.value = "" - - const result = await apiFetch("/servers", { - method: "POST", - body: payload - }) - - if (isUnauthorized(result)) { - loading.value = false - return result - } - - // Optional: direkt in die Liste einfügen - servers.value.push(result) - - loading.value = false - return result - } - - return { - servers, - loading, - error, - loadServers, - createServer - } -} diff --git a/frontend/app/layouts/default.vue b/frontend/app/layouts/default.vue deleted file mode 100644 index 54ae58a..0000000 --- a/frontend/app/layouts/default.vue +++ /dev/null @@ -1,52 +0,0 @@ - - - diff --git a/frontend/app/middleware/auth.global.ts b/frontend/app/middleware/auth.global.ts deleted file mode 100644 index 2fcc50d..0000000 --- a/frontend/app/middleware/auth.global.ts +++ /dev/null @@ -1,15 +0,0 @@ -export default defineNuxtRouteMiddleware((to, from) => { - if (import.meta.server) return // SSR ignorieren - // allow login-page - - if (to.meta.requiresAuth !== true) { - return - } - - const { token, loadToken } = useAuth() - loadToken() - - if (!token.value && to.path !== "/login") { - return navigateTo("/login") - } -}) diff --git a/frontend/app/pages/index.vue b/frontend/app/pages/index.vue deleted file mode 100644 index 8a31107..0000000 --- a/frontend/app/pages/index.vue +++ /dev/null @@ -1,7 +0,0 @@ - - diff --git a/frontend/app/pages/login.vue b/frontend/app/pages/login.vue deleted file mode 100644 index de69707..0000000 --- a/frontend/app/pages/login.vue +++ /dev/null @@ -1,64 +0,0 @@ - - - diff --git a/frontend/app/pages/owners/index.vue b/frontend/app/pages/owners/index.vue deleted file mode 100644 index d03b97c..0000000 --- a/frontend/app/pages/owners/index.vue +++ /dev/null @@ -1,96 +0,0 @@ - - - diff --git a/frontend/app/pages/servers/index.vue b/frontend/app/pages/servers/index.vue deleted file mode 100644 index ce32284..0000000 --- a/frontend/app/pages/servers/index.vue +++ /dev/null @@ -1,231 +0,0 @@ - - -