Function bodies 345 total
POST function · typescript · L88-L254 (167 LOC)src/app/api/admin/plan-request/route.ts
export async function POST(request: NextRequest) {
try {
const sessionResult = await getOwnerSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { user } = sessionResult;
const tenantId = user.tenantId;
if (!tenantId) {
return NextResponse.json({ error: 'Tenant not found' }, { status: 404 });
}
await connectDB();
// Check if there's already a pending request
const existingRequest = await PlanRequest.findOne({
tenantId,
status: 'pending',
});
if (existingRequest) {
return NextResponse.json(
{ error: 'You already have a pending plan request. Please wait for it to be processed or cancel it.' },
{ status: 400 }
);
}
const body = await request.json();
const {
requestedPlan,
billingCycle,
couponCode,
paymentMethod,
paymentNotes,
} = body;
// Validate reqDELETE function · typescript · L256-L298 (43 LOC)src/app/api/admin/plan-request/route.ts
export async function DELETE() {
try {
const sessionResult = await getOwnerSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { user } = sessionResult;
const tenantId = user.tenantId;
if (!tenantId) {
return NextResponse.json({ error: 'Tenant not found' }, { status: 404 });
}
await connectDB();
// Find and cancel the pending request
const pendingRequest = await PlanRequest.findOneAndUpdate(
{ tenantId, status: 'pending' },
{ status: 'cancelled' },
{ new: true }
);
if (!pendingRequest) {
return NextResponse.json(
{ error: 'No pending request found to cancel' },
{ status: 404 }
);
}
return NextResponse.json({
success: true,
message: 'Plan request cancelled successfully',
});
} catch (error) {
console.error('Error cancelling plan request:', error);
return NextRPUT function · typescript · L7-L51 (45 LOC)src/app/api/admin/posts/[id]/feature/route.ts
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const sessionResult = await getAdminSession();
const { id } = await params;
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { featured } = await request.json();
await connectDB();
// Get tenant context for isolation
const { tenantId } = await getTenantFromHeaders();
const userTenantId = sessionResult.user.tenantId || tenantId;
// Build filter with tenant isolation to prevent cross-tenant access
const filter: Record<string, unknown> = { _id: id };
if (userTenantId) {
filter.tenantId = userTenantId;
}
const post = await Post.findOneAndUpdate(
filter,
{ featured: Boolean(featured) },
{ new: true }
);
if (!post) {
return NextResponse.json({ error: 'Post not found' }, { status: 404 });
}
retugetValidImageUrl function · typescript · L8-L15 (8 LOC)src/app/api/admin/posts/[id]/route.ts
function getValidImageUrl(image: string | undefined | null, fallback: string): string {
if (!image || typeof image !== 'string') return fallback;
const trimmed = image.trim();
if (trimmed.startsWith('/') || trimmed.startsWith('http://') || trimmed.startsWith('https://')) {
return trimmed;
}
return fallback;
}GET function · typescript · L21-L61 (41 LOC)src/app/api/admin/posts/[id]/route.ts
export async function GET(request: NextRequest, { params }: RouteParams) {
try {
const sessionResult = await getAdminSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { user } = sessionResult;
const isAuthor = user.role === 'author';
const { id } = await params;
await connectDB();
// Get tenant context
const { tenantId } = await getTenantFromHeaders();
const userTenantId = user.tenantId || tenantId;
// Build query with tenant isolation
const query: any = { _id: id };
if (userTenantId) {
query.tenantId = userTenantId;
}
const post = await Post.findOne(query).populate('author', 'name');
if (!post) {
return NextResponse.json({ error: 'Post not found' }, { status: 404 });
}
// Authors can only access their own posts
if (isAuthor && user.authorId && post.author._id.toString() !== user.authorId) {
retPUT function · typescript · L63-L126 (64 LOC)src/app/api/admin/posts/[id]/route.ts
export async function PUT(request: NextRequest, { params }: RouteParams) {
try {
const sessionResult = await getAdminSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { user } = sessionResult;
const isAuthor = user.role === 'author';
const { id } = await params;
const body = await request.json();
let { title, description, content, image, category, tags, author, featured, published } = body;
await connectDB();
// Get tenant context
const { tenantId } = await getTenantFromHeaders();
const userTenantId = user.tenantId || tenantId;
// Build query with tenant isolation
const query: any = { _id: id };
if (userTenantId) {
query.tenantId = userTenantId;
}
const post = await Post.findOne(query);
if (!post) {
return NextResponse.json({ error: 'Post not found' }, { status: 404 });
}
// Authors can only edit DELETE function · typescript · L128-L174 (47 LOC)src/app/api/admin/posts/[id]/route.ts
export async function DELETE(request: NextRequest, { params }: RouteParams) {
try {
const sessionResult = await getAdminSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { user } = sessionResult;
const isAuthor = user.role === 'author';
const { id } = await params;
await connectDB();
// Get tenant context
const { tenantId } = await getTenantFromHeaders();
const userTenantId = user.tenantId || tenantId;
// Build query with tenant isolation
const query: any = { _id: id };
if (userTenantId) {
query.tenantId = userTenantId;
}
const post = await Post.findOne(query);
if (!post) {
return NextResponse.json({ error: 'Post not found' }, { status: 404 });
}
// Authors can only delete their own posts
if (isAuthor && user.authorId && post.author.toString() !== user.authorId) {
return NextResponse.json({ errorRepobility · code-quality intelligence platform · https://repobility.com
isValidCategory function · typescript · L12-L24 (13 LOC)src/app/api/admin/posts/route.ts
async function isValidCategory(category: string | undefined | null, tenantId: string | null): Promise<boolean> {
if (!category || typeof category !== 'string') return false;
if (tenantId) {
// For multi-tenant, check if category exists in tenant
const cat = await Category.findOne({ slug: category, tenantId });
return !!cat;
}
// Legacy fallback - check by slug
const cat = await Category.findOne({ slug: category });
return !!cat;
}GET function · typescript · L26-L89 (64 LOC)src/app/api/admin/posts/route.ts
export async function GET(request: NextRequest) {
try {
const sessionResult = await getAdminSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { user } = sessionResult;
const isAuthor = user.role === 'author';
// Parse pagination parameters
const searchParams = request.nextUrl.searchParams;
const { page, limit } = validatePagination(
searchParams.get('page') || undefined,
searchParams.get('limit') || ADMIN_PAGE_SIZE,
MAX_PAGE_SIZE
);
const skip = (page - 1) * limit;
await connectDB();
// Get tenant context
const { tenantId } = await getTenantFromHeaders();
const userTenantId = user.tenantId || tenantId;
// Build filter with tenant isolation
const filter: any = {};
// Add tenant filter if available
if (userTenantId) {
filter.tenantId = userTenantId;
}
// Authors can only see their own poPOST function · typescript · L91-L171 (81 LOC)src/app/api/admin/posts/route.ts
export async function POST(request: NextRequest) {
try {
const sessionResult = await getAdminSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { user } = sessionResult;
const isAuthor = user.role === 'author';
// Authors must have canPost permission
if (isAuthor && !user.canPost) {
return NextResponse.json({ error: 'You do not have permission to create posts' }, { status: 403 });
}
await connectDB();
// Get tenant context
const { tenantId } = await getTenantFromHeaders();
const userTenantId = user.tenantId || tenantId;
// Check tenant limits if tenantId exists
if (userTenantId) {
const limitCheck = await checkTenantLimits(userTenantId, 'posts');
if (!limitCheck.allowed) {
return NextResponse.json({ error: limitCheck.message }, { status: 403 });
}
}
const body = await request.json();
let { tGET function · typescript · L9-L67 (59 LOC)src/app/api/admin/profile/route.ts
export async function GET() {
try {
const sessionResult = await getOwnerSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { user: sessionUser } = sessionResult;
await connectDB();
const { tenantId } = await getTenantFromHeaders();
const userTenantId = sessionUser.tenantId || tenantId;
// Get user details (include password to check if set)
const user = await User.findOne({
email: sessionUser.email,
tenantId: userTenantId,
}).select('name email image phone countryCode address city country role createdAt password').lean();
if (!user) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}
// Also get author profile if exists
const author = await Author.findOne({
email: sessionUser.email,
tenantId: userTenantId,
}).select('name email avatar bio role').lean();
// Check if user hasPATCH function · typescript · L70-L181 (112 LOC)src/app/api/admin/profile/route.ts
export async function PATCH(request: NextRequest) {
try {
const sessionResult = await getOwnerSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { user: sessionUser } = sessionResult;
await connectDB();
const { tenantId } = await getTenantFromHeaders();
const userTenantId = sessionUser.tenantId || tenantId;
const body = await request.json();
const { name, image, phone, countryCode, address, city, country, bio, currentPassword, newPassword } = body;
// Update user (select password for password change)
const user = await User.findOne({
email: sessionUser.email,
tenantId: userTenantId,
}).select('+password');
if (!user) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}
// Update allowed fields (email is not editable)
if (name !== undefined) user.name = name;
if (image !== undefinedGET function · typescript · L8-L76 (69 LOC)src/app/api/admin/reviews/ai-status/route.ts
export async function GET() {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
await connectDB();
const platformSettings = await PlatformSettings.findOne().lean() as any;
const aiSettings = platformSettings?.aiSettings;
if (!aiSettings) {
return NextResponse.json({
configured: false,
provider: null,
message: 'AI settings not configured. Contact your administrator to set up AI providers.'
});
}
// Find active provider
const providers = ['groq', 'openai', 'anthropic', 'google'] as const;
let activeProvider: string | null = null;
// Try default provider first
if (aiSettings.defaultProvider && aiSettings.providers?.[aiSettings.defaultProvider]?.enabled) {
if (aiSettings.providers[aiSettings.defaultProvider].apiKey) {
activeProvider = aiSettings.defaultProvider;
}
}generateSlug function · typescript · L10-L16 (7 LOC)src/app/api/admin/reviews/generate/route.ts
function generateSlug(title: string): string {
return title
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-|-$/g, '')
.substring(0, 100);
}POST function · typescript · L19-L194 (176 LOC)src/app/api/admin/reviews/generate/route.ts
export async function POST(request: NextRequest) {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const tenantId = (session.user as any).tenantId;
if (!tenantId) {
return NextResponse.json({ error: 'No tenant associated' }, { status: 400 });
}
const body = await request.json();
const {
reviewId,
product,
sections,
affiliateLink,
customInstructions,
imageAssignments
} = body;
if (!product) {
return NextResponse.json({ error: 'Product data is required' }, { status: 400 });
}
if (!sections || !Array.isArray(sections) || sections.length === 0) {
return NextResponse.json({ error: 'At least one section is required' }, { status: 400 });
}
await connectDB();
// Get platform AI settings
const platformSettings = await PlatformSettings.findOne().lean() as any;
Repobility analyzer · published findings · https://repobility.com
GET function · typescript · L12-L41 (30 LOC)src/app/api/admin/reviews/[id]/route.ts
export async function GET(request: NextRequest, { params }: RouteParams) {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const tenantId = (session.user as any).tenantId;
if (!tenantId) {
return NextResponse.json({ error: 'No tenant associated' }, { status: 400 });
}
const { id } = await params;
await connectDB();
const review = await Review.findOne({ _id: id, tenantId })
.populate('createdBy', 'name email')
.lean();
if (!review) {
return NextResponse.json({ error: 'Review not found' }, { status: 404 });
}
return NextResponse.json({ success: true, data: review });
} catch (error: any) {
console.error('Error fetching review:', error);
return NextResponse.json({ error: error.message }, { status: 500 });
}
}PUT function · typescript · L44-L104 (61 LOC)src/app/api/admin/reviews/[id]/route.ts
export async function PUT(request: NextRequest, { params }: RouteParams) {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const userRole = (session.user as any).role;
if (userRole === 'author') {
return NextResponse.json({ error: 'Authors cannot edit reviews' }, { status: 403 });
}
const tenantId = (session.user as any).tenantId;
if (!tenantId) {
return NextResponse.json({ error: 'No tenant associated' }, { status: 400 });
}
const { id } = await params;
const body = await request.json();
await connectDB();
const review = await Review.findOne({ _id: id, tenantId });
if (!review) {
return NextResponse.json({ error: 'Review not found' }, { status: 404 });
}
// Update allowed fields
const allowedFields = [
'product',
'urls',
'generatedReview',
'featuredImage',
DELETE function · typescript · L107-L138 (32 LOC)src/app/api/admin/reviews/[id]/route.ts
export async function DELETE(request: NextRequest, { params }: RouteParams) {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const userRole = (session.user as any).role;
if (userRole === 'author') {
return NextResponse.json({ error: 'Authors cannot delete reviews' }, { status: 403 });
}
const tenantId = (session.user as any).tenantId;
if (!tenantId) {
return NextResponse.json({ error: 'No tenant associated' }, { status: 400 });
}
const { id } = await params;
await connectDB();
const review = await Review.findOneAndDelete({ _id: id, tenantId });
if (!review) {
return NextResponse.json({ error: 'Review not found' }, { status: 404 });
}
return NextResponse.json({ success: true, message: 'Review deleted' });
} catch (error: any) {
console.error('Error deleting review:', error);
return GET function · typescript · L32-L89 (58 LOC)src/app/api/admin/reviews/route.ts
export async function GET(request: NextRequest) {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const tenantId = (session.user as any).tenantId;
if (!tenantId) {
return NextResponse.json({ error: 'No tenant associated' }, { status: 400 });
}
await connectDB();
// Check feature access
const featureAccess = await canUseReviewFeature(tenantId);
if (!featureAccess.allowed) {
return NextResponse.json({
error: featureAccess.reason,
requiresUpgrade: true
}, { status: 403 });
}
const { searchParams } = new URL(request.url);
const status = searchParams.get('status');
const page = parseInt(searchParams.get('page') || '1');
const limit = parseInt(searchParams.get('limit') || '20');
const query: any = { tenantId };
if (status) {
query.status = status;
}
const [reviPOST function · typescript · L92-L152 (61 LOC)src/app/api/admin/reviews/route.ts
export async function POST(request: NextRequest) {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const userRole = (session.user as any).role;
if (userRole === 'author') {
return NextResponse.json({ error: 'Authors cannot create reviews' }, { status: 403 });
}
const tenantId = (session.user as any).tenantId;
if (!tenantId) {
return NextResponse.json({ error: 'No tenant associated' }, { status: 400 });
}
await connectDB();
// Check feature access
const featureAccess = await canUseReviewFeature(tenantId);
if (!featureAccess.allowed) {
return NextResponse.json({
error: featureAccess.reason,
requiresUpgrade: true
}, { status: 403 });
}
const body = await request.json();
const { muncheyeUrl, salesPageUrl, additionalUrls, affiliateLink } = body;
if (!muncheyeUrl && !sPOST function · typescript · L9-L123 (115 LOC)src/app/api/admin/reviews/scrape/route.ts
export async function POST(request: NextRequest) {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const tenantId = (session.user as any).tenantId;
if (!tenantId) {
return NextResponse.json({ error: 'No tenant associated' }, { status: 400 });
}
const body = await request.json();
const { reviewId, urls } = body;
if (!urls || !Array.isArray(urls) || urls.length === 0) {
return NextResponse.json({ error: 'At least one URL is required' }, { status: 400 });
}
await connectDB();
// If reviewId provided, update existing review
let review;
if (reviewId) {
review = await Review.findOne({ _id: reviewId, tenantId });
if (!review) {
return NextResponse.json({ error: 'Review not found' }, { status: 404 });
}
}
// Update status to scraping
if (review) {
review.status = 'scGET function · typescript · L9-L45 (37 LOC)src/app/api/admin/settings/route.ts
export async function GET() {
try {
const sessionResult = await getOwnerSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized - Admin access required' }, { status: 401 });
}
const { user } = sessionResult;
await connectDB();
// Get tenant context
const { tenantId } = await getTenantFromHeaders();
const userTenantId = user.tenantId || tenantId;
// Build filter with tenant isolation
const filter: any = {};
if (userTenantId) {
filter.tenantId = userTenantId;
}
// Get settings or create default for this tenant
let settings: any = await Settings.findOne(filter).lean();
if (!settings) {
const newSettings = await Settings.create({
tenantId: userTenantId || undefined,
});
settings = newSettings.toObject();
}
return NextResponse.json({ success: true, data: settings });
} catch (error: any) {
console.error('Error fetching settiPUT function · typescript · L48-L145 (98 LOC)src/app/api/admin/settings/route.ts
export async function PUT(request: NextRequest) {
try {
const sessionResult = await getOwnerSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized - Admin access required' }, { status: 401 });
}
const { user } = sessionResult;
const body = await request.json();
await connectDB();
// Get tenant context
const { tenantId } = await getTenantFromHeaders();
const userTenantId = user.tenantId || tenantId;
// Remove fields that shouldn't be updated directly
delete body._id;
delete body.__v;
delete body.createdAt;
delete body.updatedAt;
delete body.tenantId; // Don't allow changing tenantId
// Ensure numeric fields are numbers
if (body.postsPerPage !== undefined) {
body.postsPerPage = Number(body.postsPerPage);
}
if (body.featuredPostsCount !== undefined) {
body.featuredPostsCount = Number(body.featuredPostsCount);
}
if (body.latestPostsRepobility (the analyzer behind this table) · https://repobility.com
GET function · typescript · L10-L66 (57 LOC)src/app/api/admin/users/route.ts
export async function GET(request: NextRequest) {
try {
const sessionResult = await getOwnerSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized - Admin access required' }, { status: 401 });
}
const { user } = sessionResult;
// Parse pagination parameters
const searchParams = request.nextUrl.searchParams;
const { page, limit } = validatePagination(
searchParams.get('page') || undefined,
searchParams.get('limit') || ADMIN_PAGE_SIZE,
MAX_PAGE_SIZE
);
const skip = (page - 1) * limit;
await connectDB();
// Get tenant context
const { tenantId } = await getTenantFromHeaders();
const userTenantId = user.tenantId || tenantId;
// Build filter with tenant isolation
const filter: any = {};
if (userTenantId) {
filter.tenantId = userTenantId;
}
// Execute count and find in parallel for efficiency
const [total, users] = await Promise.alPATCH function · typescript · L69-L121 (53 LOC)src/app/api/admin/users/route.ts
export async function PATCH(request: NextRequest) {
try {
const sessionResult = await getOwnerSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized - Admin access required' }, { status: 401 });
}
const { user } = sessionResult;
const { userId, role } = await request.json();
if (!userId || !role) {
return NextResponse.json({ error: 'User ID and role are required' }, { status: 400 });
}
if (!['admin', 'editor', 'user'].includes(role)) {
return NextResponse.json({ error: 'Invalid role' }, { status: 400 });
}
// Prevent admin from changing their own role
if (userId === user.id) {
return NextResponse.json({ error: 'Cannot change your own role' }, { status: 400 });
}
await connectDB();
// Get tenant context
const { tenantId } = await getTenantFromHeaders();
const userTenantId = user.tenantId || tenantId;
// Build query with tenant isolation
DELETE function · typescript · L124-L174 (51 LOC)src/app/api/admin/users/route.ts
export async function DELETE(request: NextRequest) {
try {
const sessionResult = await getOwnerSession();
if (!sessionResult || !sessionResult.user) {
return NextResponse.json({ error: 'Unauthorized - Admin access required' }, { status: 401 });
}
const { user } = sessionResult;
const { searchParams } = new URL(request.url);
const userId = searchParams.get('id');
if (!userId) {
return NextResponse.json({ error: 'User ID is required' }, { status: 400 });
}
// Prevent admin from deleting themselves
if (userId === user.id) {
return NextResponse.json({ error: 'Cannot delete your own account' }, { status: 400 });
}
await connectDB();
// Get tenant context
const { tenantId } = await getTenantFromHeaders();
const userTenantId = user.tenantId || tenantId;
// Build query with tenant isolation
const query: any = { _id: userId };
if (userTenantId) {
query.tenantId = userTenantId;
}
coGET function · typescript · L10-L105 (96 LOC)src/app/api/auth/impersonate/route.ts
export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams;
const token = searchParams.get('token');
if (!token) {
return NextResponse.redirect(new URL('/admin/login?error=invalid_token', request.url));
}
// Verify impersonation token
let decoded: any;
try {
decoded = jwt.verify(token, JWT_SECRET);
} catch (err) {
return NextResponse.redirect(new URL('/admin/login?error=expired_token', request.url));
}
if (decoded.type !== 'impersonation') {
return NextResponse.redirect(new URL('/admin/login?error=invalid_token_type', request.url));
}
await connectDB();
// Verify user and tenant still exist and are valid
const [user, tenant] = await Promise.all([
User.findById(decoded.userId),
Tenant.findById(decoded.tenantId),
]);
if (!user || !tenant) {
return NextResponse.redirect(new URL('/admin/login?error=not_found', request.url));
}
POST function · typescript · L108-L121 (14 LOC)src/app/api/auth/impersonate/route.ts
export async function POST(request: NextRequest) {
try {
const response = NextResponse.json({ success: true });
// Clear impersonation cookies
response.cookies.delete('impersonation-session');
response.cookies.delete('is-impersonated');
return response;
} catch (error) {
console.error('Error ending impersonation:', error);
return NextResponse.json({ error: 'Failed to end impersonation' }, { status: 500 });
}
}GET function · typescript · L19-L69 (51 LOC)src/app/api/categories/route.ts
export async function GET() {
try {
await connectDB();
// Get tenant context from headers
const { tenantId } = await getTenantFromHeaders();
// Build filter with tenant isolation
const filter: Record<string, unknown> = {};
if (tenantId) {
filter.tenantId = tenantId;
}
// Get all post counts in single aggregation query
const postCountsResult = await Post.aggregate([
{ $match: { published: true, ...filter } },
{ $group: { _id: '$category', count: { $sum: 1 } } },
]);
// Create a map for quick lookup
const postCountMap = new Map<string, number>();
postCountsResult.forEach((item: { _id: string; count: number }) => {
postCountMap.set(item._id, item.count);
});
// Get categories
const categories = await Category.find(filter).sort({ name: 1 }).lean();
// Combine categories with counts
const categoriesWithCounts: CategoryWithCount[] = categories.map((cat: {
_id: { toString(): string };POST function · typescript · L5-L76 (72 LOC)src/app/api/contact/route.ts
export async function POST(request: NextRequest) {
// Apply rate limiting (5 requests per hour)
const rateLimitResponse = contactRateLimit.limit(request);
if (rateLimitResponse) {
return rateLimitResponse;
}
try {
const body = await request.json();
const { name, email, subject, message } = body;
// Validate required fields
if (!name || !email || !subject || !message) {
return NextResponse.json(
{ error: 'All fields are required' },
{ status: 400 }
);
}
// Validate email format
if (!isValidEmail(email)) {
return NextResponse.json(
{ error: 'Invalid email address' },
{ status: 400 }
);
}
// Validate field lengths
if (name.length > 100) {
return NextResponse.json(
{ error: 'Name is too long (max 100 characters)' },
{ status: 400 }
);
}
if (subject.length > 200) {
return NextResponse.json(
{ error: 'Subject is too long (max 200POST function · typescript · L6-L111 (106 LOC)src/app/api/coupon/validate/route.ts
export async function POST(request: NextRequest) {
try {
await connectDB();
const body = await request.json();
const { code, planSlug, originalPrice } = body;
if (!code || !planSlug || originalPrice === undefined) {
return NextResponse.json(
{ error: 'Missing required fields: code, planSlug, originalPrice' },
{ status: 400 }
);
}
// Validate plan slug
if (!['basic', 'pro', 'enterprise'].includes(planSlug)) {
return NextResponse.json(
{ error: 'Coupon not valid for free plan' },
{ status: 400 }
);
}
// Find coupon
const coupon = await Coupon.findOne({
code: code.toUpperCase().trim(),
isActive: true,
});
if (!coupon) {
return NextResponse.json(
{ valid: false, error: 'Invalid coupon code' },
{ status: 400 }
);
}
// Check expiry
if (coupon.validUntil && new Date(coupon.validUntil) < new Date()) {
return NextResponse.json(Repobility — the code-quality scanner for AI-generated software · https://repobility.com
POST function · typescript · L5-L43 (39 LOC)src/app/api/newsletter/route.ts
export async function POST(request: NextRequest) {
// Apply rate limiting (3 requests per hour)
const rateLimitResponse = newsletterRateLimit.limit(request);
if (rateLimitResponse) {
return rateLimitResponse;
}
try {
const body = await request.json();
const { email } = body;
if (!email || !isValidEmail(email)) {
return NextResponse.json(
{ success: false, error: 'Valid email is required' },
{ status: 400 }
);
}
// TODO: Integrate with your newsletter service (Mailchimp, Resend, etc.)
// Example with Resend:
// await resend.contacts.create({
// email,
// audienceId: process.env.RESEND_AUDIENCE_ID,
// });
console.log(`Newsletter subscription: ${email}`);
return NextResponse.json({
success: true,
message: 'Successfully subscribed to newsletter',
});
} catch (error) {
console.error('Newsletter subscription error:', error);
return NextResponse.json(
{ success: fGET function · typescript · L6-L26 (21 LOC)src/app/api/plans/route.ts
export async function GET() {
try {
await connectDB();
const plans = await Plan.find({ isActive: true })
.sort({ sortOrder: 1 })
.select('name slug description price limits features sortOrder')
.lean();
return NextResponse.json({
success: true,
data: plans,
});
} catch (error) {
console.error('Error fetching plans:', error);
return NextResponse.json(
{ error: 'Failed to fetch plans' },
{ status: 500 }
);
}
}GET function · typescript · L4-L40 (37 LOC)src/app/api/posts/route.ts
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const category = searchParams.get('category');
const tag = searchParams.get('tag');
const page = parseInt(searchParams.get('page') || '1', 10);
const limit = parseInt(searchParams.get('limit') || '10', 10);
// Validate pagination parameters
const validPage = Math.max(1, page);
const validLimit = Math.min(Math.max(1, limit), 100); // Max 100 items per page
let posts;
if (category) {
posts = await getPostsByCategory(category);
} else if (tag) {
posts = await getPostsByTag(tag);
} else {
posts = await getAllPosts();
}
// Pagination
const startIndex = (validPage - 1) * validLimit;
const endIndex = startIndex + validLimit;
const paginatedPosts = posts.slice(startIndex, endIndex);
return NextResponse.json({
success: true,
data: paginatedPosts,
meta: {
total: posts.length,
page: validPage,
limit: validLimit,
GET function · typescript · L6-L52 (47 LOC)src/app/api/public/[tenant]/pages/route.ts
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ tenant: string }> }
) {
try {
const { tenant: tenantSlug } = await params;
const { searchParams } = new URL(request.url);
const location = searchParams.get('location'); // 'navbar' | 'footer' | 'all'
await connectDB();
// Find tenant
const tenant = await Tenant.findOne({ slug: tenantSlug.toLowerCase() });
if (!tenant) {
return NextResponse.json({ error: 'Tenant not found' }, { status: 404 });
}
// Build query
const query: any = { tenantId: tenant._id, published: true };
if (location === 'navbar') {
query.showInNavbar = true;
} else if (location === 'footer') {
query.showInFooter = true;
}
// Fetch pages
const pages = await Page.find(query)
.select('title slug showInNavbar showInFooter navbarOrder footerOrder')
.sort({ navbarOrder: 1, footerOrder: 1 })
.lean();
return NextResponse.json({
sucGET function · typescript · L5-L52 (48 LOC)src/app/api/search/route.ts
export async function GET(request: NextRequest) {
// Apply rate limiting (30 requests per minute)
const rateLimitResponse = searchRateLimit.limit(request);
if (rateLimitResponse) {
return rateLimitResponse;
}
const searchParams = request.nextUrl.searchParams;
const query = searchParams.get('q');
const tenantId = searchParams.get('tenantId') || undefined;
const limit = Math.min(100, Math.max(1, parseInt(searchParams.get('limit') || '50')));
if (!query) {
return NextResponse.json(
{ success: false, error: 'Search query is required' },
{ status: 400 }
);
}
// Validate query length to prevent abuse
if (query.length > 200) {
return NextResponse.json(
{ success: false, error: 'Search query too long (max 200 characters)' },
{ status: 400 }
);
}
try {
const posts = await searchPosts(query, tenantId, limit);
return NextResponse.json({
success: true,
data: posts,
meta: {
query,
GET function · typescript · L6-L33 (28 LOC)src/app/api/settings/route.ts
export async function GET() {
try {
await connectDB();
const settings = await Settings.findOne().lean();
if (!settings) {
return NextResponse.json({
success: true,
data: {
branding: {
enabled: false,
},
},
});
}
// Only return branding settings for public
return NextResponse.json({
success: true,
data: {
branding: settings.branding,
},
});
} catch (error: any) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
}getClientIP function · typescript · L14-L18 (5 LOC)src/app/api/super-admin/auth/login/route.ts
function getClientIP(request: NextRequest): string {
const forwarded = request.headers.get('x-forwarded-for');
const realIP = request.headers.get('x-real-ip');
return forwarded?.split(',')[0]?.trim() || realIP || 'unknown';
}recordAttempt function · typescript · L38-L59 (22 LOC)src/app/api/super-admin/auth/login/route.ts
function recordAttempt(ip: string, success: boolean): void {
if (success) {
// Clear attempts on successful login
loginAttempts.delete(ip);
return;
}
const now = Date.now();
const attempts = loginAttempts.get(ip);
if (attempts) {
loginAttempts.set(ip, {
count: attempts.count + 1,
lastAttempt: now,
});
} else {
loginAttempts.set(ip, {
count: 1,
lastAttempt: now,
});
}
}Repobility · code-quality intelligence platform · https://repobility.com
POST function · typescript · L61-L179 (119 LOC)src/app/api/super-admin/auth/login/route.ts
export async function POST(request: NextRequest) {
try {
// Rate limiting check
const clientIP = getClientIP(request);
const rateLimitResult = isRateLimited(clientIP);
if (rateLimitResult.limited) {
return NextResponse.json(
{
error: 'Too many login attempts. Please try again later.',
retryAfter: rateLimitResult.remainingTime,
},
{ status: 429 }
);
}
const body = await request.json();
const { email, password } = body;
if (!email || !password) {
return NextResponse.json(
{ error: 'Email and password are required' },
{ status: 400 }
);
}
// Validate email format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return NextResponse.json(
{ error: 'Invalid email format' },
{ status: 400 }
);
}
await connectDB();
// Find super admin and include password field
const admin = await SPOST function · typescript · L3-L20 (18 LOC)src/app/api/super-admin/auth/logout/route.ts
export async function POST() {
const response = NextResponse.json({
success: true,
message: 'Logged out successfully',
});
// Clear the cookie
const useSecureCookie = process.env.USE_SECURE_COOKIES === 'true';
response.cookies.set('super-admin-token', '', {
httpOnly: true,
secure: useSecureCookie,
sameSite: 'lax',
maxAge: 0,
path: '/',
});
return response;
}GET function · typescript · L34-L153 (120 LOC)src/app/api/super-admin/authors/route.ts
export async function GET(request: NextRequest) {
try {
// Verify super admin
const cookieStore = await cookies();
const token = cookieStore.get('super-admin-token')?.value;
if (!token) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const session = await verifySuperAdminToken(token);
if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
await connectDB();
const searchParams = request.nextUrl.searchParams;
const page = Math.max(1, parseInt(searchParams.get('page') || '1'));
const limit = Math.min(100, Math.max(1, parseInt(searchParams.get('limit') || '20')));
const search = searchParams.get('search')?.trim() || '';
const canLogin = searchParams.get('canLogin');
const canPost = searchParams.get('canPost');
// Build query
const matchStage: Record<string, unknown> = {};
if (search) {
matchStage.$or = [
{ name: { $regex: searcGET function · typescript · L8-L68 (61 LOC)src/app/api/super-admin/auth/session/route.ts
export async function GET(request: NextRequest) {
try {
const token = request.cookies.get('super-admin-token')?.value;
if (!token) {
return NextResponse.json(
{ authenticated: false },
{ status: 401 }
);
}
// Verify token
let decoded: any;
try {
decoded = jwt.verify(token, JWT_SECRET);
} catch (err) {
return NextResponse.json(
{ authenticated: false, error: 'Invalid token' },
{ status: 401 }
);
}
// Check if token is for super admin
if (decoded.type !== 'super-admin') {
return NextResponse.json(
{ authenticated: false, error: 'Invalid token type' },
{ status: 401 }
);
}
await connectDB();
// Get super admin
const admin = await SuperAdmin.findById(decoded.id);
if (!admin || !admin.isActive) {
return NextResponse.json(
{ authenticated: false },
{ status: 401 }
);
}
return NextResponse.json({
verifySuperAdmin function · typescript · L11-L28 (18 LOC)src/app/api/super-admin/coupons/[id]/route.ts
async function verifySuperAdmin() {
const cookieStore = await cookies();
const token = cookieStore.get('super-admin-token')?.value;
if (!token) {
return null;
}
try {
const decoded = jwt.verify(token, JWT_SECRET) as any;
if (decoded.type !== 'super-admin') {
return null;
}
return decoded;
} catch {
return null;
}
}GET function · typescript · L30-L71 (42 LOC)src/app/api/super-admin/coupons/[id]/route.ts
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const admin = await verifySuperAdmin();
if (!admin) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { id } = await params;
if (!mongoose.Types.ObjectId.isValid(id)) {
return NextResponse.json({ error: 'Invalid coupon ID' }, { status: 400 });
}
await connectDB();
const coupon = await Coupon.findById(id).lean();
if (!coupon) {
return NextResponse.json({ error: 'Coupon not found' }, { status: 404 });
}
// Get usage details
const usageCount = await CouponUsage.countDocuments({ couponId: id });
return NextResponse.json({
success: true,
data: {
...coupon,
usageCount,
},
});
} catch (error) {
console.error('Error fetching coupon:', error);
return NextResponse.json(
{ error: 'Failed to fetch coupon' },
{ status: 500 PATCH function · typescript · L73-L152 (80 LOC)src/app/api/super-admin/coupons/[id]/route.ts
export async function PATCH(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const admin = await verifySuperAdmin();
if (!admin) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { id } = await params;
if (!mongoose.Types.ObjectId.isValid(id)) {
return NextResponse.json({ error: 'Invalid coupon ID' }, { status: 400 });
}
await connectDB();
const coupon = await Coupon.findById(id);
if (!coupon) {
return NextResponse.json({ error: 'Coupon not found' }, { status: 404 });
}
const body = await request.json();
const {
name,
description,
discountType,
discountValue,
validPlans,
maxUsageTotal,
maxUsagePerTenant,
validFrom,
validUntil,
isActive,
} = body;
// Validate discount value if provided
if (discountType && discountValue !== undefined) {
if (discountType === 'percentage' &&DELETE function · typescript · L154-L201 (48 LOC)src/app/api/super-admin/coupons/[id]/route.ts
export async function DELETE(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const admin = await verifySuperAdmin();
if (!admin) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { id } = await params;
if (!mongoose.Types.ObjectId.isValid(id)) {
return NextResponse.json({ error: 'Invalid coupon ID' }, { status: 400 });
}
await connectDB();
// Check if coupon has been used
const usageCount = await CouponUsage.countDocuments({ couponId: id });
if (usageCount > 0) {
// Don't delete, just deactivate
await Coupon.findByIdAndUpdate(id, { isActive: false });
return NextResponse.json({
success: true,
message: 'Coupon has been deactivated (it has usage history)',
});
}
const coupon = await Coupon.findByIdAndDelete(id);
if (!coupon) {
return NextResponse.json({ error: 'Coupon not found' }, { status: 404 });
}Repobility analyzer · published findings · https://repobility.com
verifySuperAdmin function · typescript · L10-L27 (18 LOC)src/app/api/super-admin/coupons/route.ts
async function verifySuperAdmin() {
const cookieStore = await cookies();
const token = cookieStore.get('super-admin-token')?.value;
if (!token) {
return null;
}
try {
const decoded = jwt.verify(token, JWT_SECRET) as any;
if (decoded.type !== 'super-admin') {
return null;
}
return decoded;
} catch {
return null;
}
}GET function · typescript · L29-L102 (74 LOC)src/app/api/super-admin/coupons/route.ts
export async function GET(request: NextRequest) {
try {
const admin = await verifySuperAdmin();
if (!admin) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
await connectDB();
const { searchParams } = new URL(request.url);
const page = Math.max(1, parseInt(searchParams.get('page') || '1'));
const limit = Math.min(100, Math.max(1, parseInt(searchParams.get('limit') || '10')));
const search = searchParams.get('search')?.trim() || '';
const status = searchParams.get('status') || '';
const skip = (page - 1) * limit;
// Build filter
const filter: any = {};
if (search) {
filter.$or = [
{ code: { $regex: search, $options: 'i' } },
{ name: { $regex: search, $options: 'i' } },
];
}
const now = new Date();
if (status === 'active') {
filter.isActive = true;
filter.validFrom = { $lte: now };
filter.$or = [
{ validUntil: null },
{ validUPOST function · typescript · L104-L197 (94 LOC)src/app/api/super-admin/coupons/route.ts
export async function POST(request: NextRequest) {
try {
const admin = await verifySuperAdmin();
if (!admin) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
await connectDB();
const body = await request.json();
const {
code,
name,
description,
discountType,
discountValue,
validPlans,
maxUsageTotal,
maxUsagePerTenant,
validFrom,
validUntil,
isActive,
} = body;
// Validate required fields
if (!code || !name || !discountType || discountValue === undefined || !validFrom) {
return NextResponse.json(
{ error: 'Missing required fields: code, name, discountType, discountValue, validFrom' },
{ status: 400 }
);
}
// Check if code already exists
const existingCoupon = await Coupon.findOne({
code: code.toUpperCase().trim(),
});
if (existingCoupon) {
return NextResponse.json(
{ error: 'A coupo