first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:46:42 +03:00
commit 2a5b661443
202 changed files with 49770 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
import { NextRequest } from "next/server"
import { handleImageProxyRequest } from "@/lib/api-proxy"
export async function PUT(
req: NextRequest,
context: { params: Promise<{ id: string }> }
) {
const { id } = await context.params
return handleImageProxyRequest(req, `/admin/heroes/${id}`)
}

View File

@@ -0,0 +1,6 @@
import { NextRequest } from "next/server"
import { handleImageProxyRequest } from "@/lib/api-proxy"
export async function POST(req: NextRequest) {
return handleImageProxyRequest(req, "/admin/heroes")
}

View File

@@ -0,0 +1,11 @@
import { NextRequest } from "next/server";
import { handleImageProxyRequest } from "@/lib/api-proxy";
export async function PUT(
req: NextRequest,
context: { params: Promise<{ id: string }> }
) {
const { id } = await context.params;
console.log("API Route PUT called with id:", id);
return handleImageProxyRequest(req, `/admin/posts/${id}`);
}

View File

@@ -0,0 +1,6 @@
import { NextRequest } from "next/server";
import { handleImageProxyRequest } from "@/lib/api-proxy";
export async function POST(req: NextRequest) {
return handleImageProxyRequest(req, "/admin/posts");
}

View File

@@ -0,0 +1,10 @@
import { NextRequest } from "next/server"
import { handleImageProxyRequest } from "@/lib/api-proxy"
export async function PUT(
req: NextRequest,
context: { params: Promise<{ id: string }> }
) {
const { id } = await context.params
return handleImageProxyRequest(req, `/admin/settings/${id}`)
}

View File

@@ -0,0 +1,6 @@
import { NextRequest } from "next/server"
import { handleImageProxyRequest } from "@/lib/api-proxy"
export async function POST(req: NextRequest) {
return handleImageProxyRequest(req, "/admin/settings")
}

View File

@@ -0,0 +1,187 @@
import NextAuth, { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import GitHubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
import { JWT } from "next-auth/jwt";
// Helper to get API URL consistently
const API_URL = process.env.NEXT_PUBLIC_API_URL || process.env.BASE_API_URL || "http://localhost:8080/api";
/**
* Refresh token ile yeni access token al
*/
async function refreshAccessToken(token: JWT) {
try {
const response = await fetch(`${API_URL}/api/v1/auth/refresh`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
refresh_token: token.refreshToken,
}),
});
if (!response.ok) {
throw new Error("Failed to refresh token");
}
const refreshedTokens = await response.json();
return {
...token,
accessToken: refreshedTokens.access_token,
refreshToken: refreshedTokens.refresh_token ?? token.refreshToken,
accessTokenExpires: Date.now() + 15 * 60 * 1000, // 15 dakika (Time should ideally come from backend)
};
} catch (error) {
console.error("Error refreshing access token:", error);
return {
...token,
error: "RefreshAccessTokenError",
};
}
}
const authOptions: NextAuthOptions = {
providers: [
CredentialsProvider({
name: "Credentials",
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
// Optional: used if redirecting from a separate auth flow
accessToken: { label: "Access Token", type: "text" },
refreshToken: { label: "Refresh Token", type: "text" },
},
async authorize(credentials) {
// 1. External Token Flow (if tokens are passed directly, e.g. from OAuth on backend)
if (credentials?.accessToken && credentials?.refreshToken) {
try {
// Validate token and get user info
const meResponse = await fetch(`${API_URL}/api/v1/auth/me`, {
headers: {
"Authorization": `Bearer ${credentials.accessToken}`,
},
});
if (!meResponse.ok) return null;
const userData = await meResponse.json();
return {
id: userData.id?.toString(),
email: userData.email,
name: userData.username,
username: userData.username, // Added to satisfy User interface
is_admin: userData.is_admin, // Capture is_admin
accessToken: credentials.accessToken,
refreshToken: credentials.refreshToken,
accessTokenExpires: Date.now() + 15 * 60 * 1000,
};
} catch {
return null;
}
}
// 2. Standard Email/Password Flow
if (!credentials?.email || !credentials?.password) {
return null;
}
try {
const response = await fetch(`${API_URL}/api/v1/auth/login`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: credentials.email,
password: credentials.password,
}),
});
if (!response.ok) {
return null;
}
const data = await response.json();
// Structure matches user's provided JSON example
return {
id: data.user.id.toString(),
email: data.user.email,
name: data.user.username,
username: data.user.username, // Added to satisfy User interface
is_admin: data.user.is_admin, // Capture is_admin
accessToken: data.access_token,
refreshToken: data.refresh_token,
accessTokenExpires: Date.now() + 15 * 60 * 1000,
};
} catch (error) {
console.error("Login error:", error);
return null;
}
},
}),
// Keep existing providers if they are configured
GitHubProvider({
clientId: process.env.GITHUB_CLIENT_ID || "",
clientSecret: process.env.GITHUB_CLIENT_SECRET || "",
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID || "",
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
}),
],
pages: {
signIn: "/auth/login",
signOut: "/auth/login",
error: "/auth/login",
},
callbacks: {
async jwt({ token, user }) {
// Initial sign in
if (user) {
token.id = user.id;
token.email = user.email;
token.name = user.name || undefined;
token.username = user.username;
token.accessToken = user.accessToken;
token.refreshToken = user.refreshToken;
token.roles = user.roles;
token.is_admin = user.is_admin;
token.accessTokenExpires = user.accessTokenExpires;
}
// Return previous token if the access token has not expired yet
if (Date.now() < (token.accessTokenExpires as number)) {
return token;
}
// Access token has expired, try to update it
return refreshAccessToken(token);
},
async session({ session, token }) {
if (token) {
session.user.id = token.id as string;
session.user.email = token.email as string;
session.user.name = token.name as string;
session.user.username = token.username as string;
session.user.is_admin = token.is_admin as boolean; // Expose is_admin to session
session.accessToken = token.accessToken as string;
session.user.accessToken = token.accessToken as string;
session.error = token.error as string;
}
return session;
},
},
session: {
strategy: "jwt",
},
secret: process.env.NEXTAUTH_SECRET, // Ensure this matches .env
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };