fix some minor issues
This commit is contained in:
parent
3141ba60f4
commit
ac5288aa4c
18
.dockerignore
Normal file
18
.dockerignore
Normal file
@ -0,0 +1,18 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
.next
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.env
|
||||
.env*.local
|
||||
.env*.development
|
||||
.env*.production
|
||||
.vscode/
|
||||
.git/
|
||||
*.tgz
|
||||
# SQLite dev databases, falls verwendet
|
||||
prisma/dev.db*
|
||||
prisma/dev.db-journal*
|
||||
# Migrations werden normalerweise nicht im App-Image ausgeführt
|
||||
prisma/migrations
|
||||
73
Dockerfile
Normal file
73
Dockerfile
Normal file
@ -0,0 +1,73 @@
|
||||
# Stage 1: Basis-Abhängigkeiten installieren und Prisma Client generieren
|
||||
# Diese Stufe dient dazu, alle notwendigen Abhängigkeiten (inkl. devDependencies für den Build)
|
||||
# zu installieren und den Prisma Client zu generieren.
|
||||
FROM node:18-alpine AS base
|
||||
WORKDIR /app
|
||||
|
||||
# Kopiere package.json und package-lock.json (oder yarn.lock, pnpm-lock.yaml)
|
||||
COPY package.json package-lock.json* ./
|
||||
|
||||
# Installiere Abhängigkeiten sauber basierend auf dem Lockfile
|
||||
RUN npm ci
|
||||
|
||||
# Kopiere das Prisma-Schema-Verzeichnis
|
||||
COPY prisma ./prisma
|
||||
|
||||
# Generiere den Prisma Client. Dieser wird für den Build-Prozess benötigt.
|
||||
# Der generierte Client landet in node_modules/.prisma/client
|
||||
RUN npx prisma generate
|
||||
|
||||
# Stage 2: Anwendung bauen
|
||||
# Diese Stufe verwendet die Abhängigkeiten und den Prisma Client aus der 'base'-Stufe,
|
||||
# um die Next.js-Anwendung zu bauen.
|
||||
FROM node:18-alpine AS builder
|
||||
WORKDIR /app
|
||||
|
||||
# Kopiere die installierten node_modules aus der 'base'-Stufe
|
||||
COPY --from=base /app/node_modules ./node_modules
|
||||
|
||||
# Kopiere das Prisma-Verzeichnis (Schema und ggf. generierter Client, falls außerhalb von node_modules)
|
||||
# Obwohl der Client in node_modules ist, kann das Schema für den Build-Prozess referenziert werden.
|
||||
COPY --from=base /app/prisma ./prisma
|
||||
|
||||
# Kopiere den Rest des Anwendungscodes
|
||||
COPY . .
|
||||
|
||||
# Setze die Umgebungsvariable für den Produktions-Build
|
||||
ENV NODE_ENV production
|
||||
|
||||
# Führe den Build-Befehl aus.
|
||||
# Dieser Befehl sollte die `output: 'standalone'` Konfiguration in next.config.js nutzen.
|
||||
RUN npm run build
|
||||
|
||||
# Stage 3: Produktions-Image
|
||||
# Diese Stufe erstellt das endgültige, schlanke Image für den Betrieb der Anwendung.
|
||||
FROM node:18-alpine AS runner
|
||||
WORKDIR /app
|
||||
|
||||
# Setze die Umgebung auf Produktion
|
||||
ENV NODE_ENV production
|
||||
# Setze einen Standard-Port, dieser kann zur Laufzeit durch die Umgebungsvariable PORT überschrieben werden
|
||||
ENV PORT 3000
|
||||
|
||||
# Kopiere den 'standalone'-Output aus der 'builder'-Stufe.
|
||||
# Dieser Ordner enthält einen minimalen server.js und nur die notwendigen node_modules.
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
|
||||
# Kopiere statische Assets (.next/static)
|
||||
COPY --from=builder /app/.next/static ./.next/static
|
||||
|
||||
# Kopiere öffentliche Assets (public Ordner)
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
# Das Prisma-Schema wird vom Prisma Client zur Laufzeit benötigt, um die
|
||||
# Datenbankverbindungsinformationen aus den `datasources` zu lesen.
|
||||
# Der 'standalone'-Output könnte dies nicht automatisch einbeziehen.
|
||||
# Es ist sicherer, es explizit zu kopieren.
|
||||
COPY --from=builder /app/prisma ./prisma
|
||||
|
||||
# Gib den Port frei, auf dem die Next.js-Anwendung laufen wird
|
||||
EXPOSE 3000
|
||||
|
||||
# Der Befehl zum Starten des Next.js-Servers aus dem 'standalone'-Output
|
||||
CMD ["node", "server.js"]
|
||||
@ -3,6 +3,7 @@ import type { NextConfig } from "next";
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
reactStrictMode: true,
|
||||
output: "standalone"
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
declare global {
|
||||
var prisma: PrismaClient | undefined;
|
||||
let prisma: PrismaClient | undefined;
|
||||
}
|
||||
|
||||
const globalForPrisma = global as typeof globalThis & { prisma?: PrismaClient };
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
// Datei: pages/api/admin/users/[userId]/transactions.ts
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { getServerSession } from 'next-auth/next';
|
||||
import { authOptions } from '../../../auth/[...nextauth]'; // Pfad anpassen
|
||||
import type {NextApiRequest, NextApiResponse} from 'next';
|
||||
import {getServerSession} from 'next-auth/next';
|
||||
import {authOptions} from '../../../auth/[...nextauth]'; // Pfad anpassen
|
||||
import prisma from '../../../../../lib/prisma'; // Pfad anpassen
|
||||
import { Transaction, User } from '@prisma/client'; // Importiere relevante Typen
|
||||
import {Prisma, Transaction} from '@prisma/client'; // Importiere relevante Typen
|
||||
|
||||
// Erweitere den Transaction-Typ, um optional den auslösenden Admin einzuschließen
|
||||
type TransactionWithAdmin = Transaction & {
|
||||
@ -33,26 +33,26 @@ export default async function handler(
|
||||
) {
|
||||
if (req.method !== 'GET') {
|
||||
res.setHeader('Allow', ['GET']);
|
||||
return res.status(405).json({ message: `Method ${req.method} Not Allowed` });
|
||||
return res.status(405).json({message: `Method ${req.method} Not Allowed`});
|
||||
}
|
||||
|
||||
// Admin-Session abrufen und validieren
|
||||
const session = await getServerSession(req, res, authOptions);
|
||||
if (!session || !session.user || session.user.role !== 'admin') {
|
||||
return res.status(403).json({ message: 'Zugriff verweigert. Nur für Administratoren.' });
|
||||
return res.status(403).json({message: 'Zugriff verweigert. Nur für Administratoren.'});
|
||||
}
|
||||
|
||||
// Zielbenutzer-ID aus der URL extrahieren
|
||||
const { userId: targetUserId } = req.query;
|
||||
const {userId: targetUserId} = req.query;
|
||||
if (typeof targetUserId !== 'string') {
|
||||
return res.status(400).json({ message: 'Ungültige Benutzer-ID in der URL.' });
|
||||
return res.status(400).json({message: 'Ungültige Benutzer-ID in der URL.'});
|
||||
}
|
||||
|
||||
try {
|
||||
// Zuerst den Zielbenutzer finden, um sicherzustellen, dass er existiert
|
||||
// und um seine Details in der Antwort mitzugeben.
|
||||
const targetUser = await prisma.user.findUnique({
|
||||
where: { id: targetUserId },
|
||||
where: {id: targetUserId},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
@ -61,7 +61,7 @@ export default async function handler(
|
||||
});
|
||||
|
||||
if (!targetUser) {
|
||||
return res.status(404).json({ message: 'Zielbenutzer nicht gefunden.' });
|
||||
return res.status(404).json({message: 'Zielbenutzer nicht gefunden.'});
|
||||
}
|
||||
|
||||
// Transaktionen für den Zielbenutzer abrufen
|
||||
@ -93,11 +93,13 @@ export default async function handler(
|
||||
totalTransactions: transactions.length,
|
||||
});
|
||||
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error(`Fehler beim Abrufen des Transaktionsverlaufs für Benutzer ${targetUserId}:`, error);
|
||||
if (error.code === 'P2025') { // Prisma: Record to query not found (kann bei Relationen auftreten)
|
||||
return res.status(404).json({ message: 'Fehler beim Laden der zugehörigen Daten (Prisma P2025).' });
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
if (error.code === 'P2025') { // Prisma: Record to query not found (kann bei Relationen auftreten)
|
||||
return res.status(404).json({message: 'Fehler beim Laden der zugehörigen Daten (Prisma P2025).'});
|
||||
}
|
||||
}
|
||||
return res.status(500).json({ message: 'Interner Serverfehler beim Abrufen des Transaktionsverlaufs.' });
|
||||
return res.status(500).json({message: 'Interner Serverfehler beim Abrufen des Transaktionsverlaufs.'});
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ export const authOptions: AuthOptions = {
|
||||
email: { label: "E-Mail", type: "email", placeholder: "user@example.com" },
|
||||
password: { label: "Passwort", type: "password" }
|
||||
},
|
||||
async authorize(credentials, req) {
|
||||
async authorize(credentials) {
|
||||
if (!credentials?.email || !credentials.password) {
|
||||
throw new Error("E-Mail und Passwort sind erforderlich.");
|
||||
}
|
||||
|
||||
@ -6,15 +6,16 @@ import { useEffect, useState } from 'react';
|
||||
import type { ClientSafeProvider, LiteralUnion } from 'next-auth/react';
|
||||
import type { ParsedUrlQuery } from 'querystring'; // Für GetServerSidePropsContext
|
||||
import type { PreviewData } from 'next/dist/types';
|
||||
import {BuiltInProviderType} from "next-auth/providers/index"; // Für GetServerSidePropsContext
|
||||
import {BuiltInProviderType} from "next-auth/providers/index";
|
||||
import Link from "next/link"; // Für GetServerSidePropsContext
|
||||
|
||||
interface SignInProps {
|
||||
providers: Record<LiteralUnion<BuiltInProviderType, string>, ClientSafeProvider> | null;
|
||||
csrfToken: string | undefined;
|
||||
}
|
||||
|
||||
const SignInPage: NextPage<SignInProps> = ({ providers, csrfToken }) => {
|
||||
const { data: session, status } = useSession();
|
||||
const SignInPage: NextPage<SignInProps> = ({ providers}) => {
|
||||
const {status } = useSession();
|
||||
const router = useRouter();
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
@ -186,10 +187,9 @@ const SignInPage: NextPage<SignInProps> = ({ providers, csrfToken }) => {
|
||||
<div className="mt-6 text-center text-sm">
|
||||
<p className="text-gray-600">
|
||||
Noch kein Konto?{' '}
|
||||
<a href="/auth/signup" className="font-medium text-indigo-600 hover:text-indigo-500">
|
||||
<Link href="/auth/signup" className="font-medium text-indigo-600 hover:text-indigo-500">
|
||||
Registrieren
|
||||
</a>
|
||||
{/* TODO: Registrierungsseite erstellen */}
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user