main
Some checks failed
Backend Deploy 🚀 / build-and-deploy (push) Has been cancelled

This commit is contained in:
Harun CAN
2026-04-05 17:28:49 +03:00
parent adc6e34fca
commit 9f17ced37d
3 changed files with 199 additions and 11 deletions

117
prisma/seed-admin.ts Normal file
View File

@@ -0,0 +1,117 @@
import { PrismaClient } from '@prisma/client';
import * as bcrypt from 'bcrypt';
/**
* Admin Seed Script
*
* Admin hesabı ve sınırsız kredi ataması:
* - Email: admin@contentgen.ai
* - Şifre: Admin123!
* - Rol: admin (sınırsız erişim)
* - Kredi: 999999
*/
const prisma = new PrismaClient();
async function main() {
console.log('🌱 Admin seed başlatılıyor...');
// 1. Admin rolü oluştur/bul
const adminRole = await prisma.role.upsert({
where: { name: 'admin' },
update: {},
create: {
name: 'admin',
description: 'Sistem yöneticisi — sınırsız erişim',
isSystem: true,
},
});
console.log(`✅ Admin rolü: ${adminRole.id}`);
// 2. User rolü oluştur/bul (her kullanıcıda olmalı)
const userRole = await prisma.role.upsert({
where: { name: 'user' },
update: {},
create: {
name: 'user',
description: 'Standart kullanıcı',
isSystem: true,
},
});
// 3. Admin kullanıcısı oluştur
const hashedPassword = await bcrypt.hash('Admin123!', 12);
const adminUser = await prisma.user.upsert({
where: { email: 'admin@contentgen.ai' },
update: {
password: hashedPassword,
firstName: 'Admin',
lastName: 'ContentGen',
isActive: true,
},
create: {
email: 'admin@contentgen.ai',
password: hashedPassword,
firstName: 'Admin',
lastName: 'ContentGen',
isActive: true,
},
});
console.log(`✅ Admin kullanıcısı: ${adminUser.id} (${adminUser.email})`);
// 4. Rolleri ata (upsert ile — varsa atlama)
for (const role of [adminRole, userRole]) {
await prisma.userRole.upsert({
where: {
userId_roleId: {
userId: adminUser.id,
roleId: role.id,
},
},
update: {},
create: {
userId: adminUser.id,
roleId: role.id,
},
});
}
console.log('✅ Roller atandı: admin + user');
// 5. Sınırsız kredi yükle (mevcut bakiye kontrol et)
const existingTransactions = await prisma.creditTransaction.findMany({
where: { userId: adminUser.id },
});
const currentBalance = existingTransactions.reduce((sum, tx) => sum + tx.amount, 0);
if (currentBalance < 1000) {
const creditAmount = 999999 - currentBalance;
await prisma.creditTransaction.create({
data: {
userId: adminUser.id,
amount: creditAmount,
type: 'grant',
description: 'Admin hesabı — sınırsız kredi',
balanceAfter: 999999,
},
});
console.log(`✅ Kredi yüklendi: +${creditAmount} (toplam: 999,999)`);
} else {
console.log(` Yeterli kredi mevcut: ${currentBalance}`);
}
console.log('\n═══════════════════════════════════════');
console.log('🔑 Admin Giriş Bilgileri:');
console.log(' Email: admin@contentgen.ai');
console.log(' Şifre: Admin123!');
console.log('═══════════════════════════════════════\n');
}
main()
.catch((e) => {
console.error('❌ Seed hatası:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});

View File

@@ -122,26 +122,61 @@ export class AdminService {
// ── Proje ve Render Yönetimi ──────────────────────────────────────
async getAllProjects() {
return this.prisma.project.findMany({
include: { user: { select: { email: true, firstName: true, lastName: true } } },
orderBy: { createdAt: 'desc' },
});
async getAllProjects(params: { page: number; limit: number; status?: string; userId?: string }) {
const { page, limit, status, userId } = params;
// Status filtresini prisma tarafında idari bir kontrole dönüştürmek gerek
const whereCondition: any = { deletedAt: null };
if (status) whereCondition.status = status;
if (userId) whereCondition.userId = userId;
const [data, total] = await Promise.all([
this.prisma.project.findMany({
where: whereCondition,
include: { user: { select: { email: true, firstName: true, lastName: true } } },
orderBy: { createdAt: 'desc' },
skip: (page - 1) * limit,
take: limit,
}),
this.prisma.project.count({ where: whereCondition }),
]);
return { data, total, page, limit, totalPages: Math.ceil(total / limit) };
}
async getAllRenderJobs() {
return this.prisma.renderJob.findMany({
include: { project: { select: { name: true } } },
orderBy: { createdAt: 'desc' },
async getAllRenderJobs(params: { page: number; limit: number; status?: string }) {
const { page, limit, status } = params;
const whereCondition: any = {};
if (status) whereCondition.status = status;
const [data, total] = await Promise.all([
this.prisma.renderJob.findMany({
where: whereCondition,
include: { project: { select: { title: true } } },
orderBy: { createdAt: 'desc' },
skip: (page - 1) * limit,
take: limit,
}),
this.prisma.renderJob.count({ where: whereCondition }),
]);
return { data, total, page, limit, totalPages: Math.ceil(total / limit) };
}
async adminDeleteProject(projectId: string) {
return this.prisma.project.update({
where: { id: projectId },
data: { deletedAt: new Date() },
});
}
// ── Kullanıcı Yönetimi ────────────────────────────────────────────
async banUser(userId: string, isBanned: boolean) {
async setUserActive(userId: string, isActive: boolean) {
return this.prisma.user.update({
where: { id: userId },
data: { isActive: !isBanned },
data: { isActive },
});
}

View File

@@ -149,10 +149,35 @@ export class BillingService {
return plans;
}
/**
* Kullanıcının admin rolü olup olmadığını kontrol et
*/
private async isAdmin(userId: string): Promise<boolean> {
const userRoles = await this.db.userRole.findMany({
where: { userId },
include: { role: true },
});
return userRoles.some((ur) => ur.role.name === 'admin' || ur.role.name === 'superadmin');
}
/**
* Kullanıcı kredi bakiyesi
*/
async getCreditBalance(userId: string) {
// Admin kullanıcılar için sınırsız kredi
const admin = await this.isAdmin(userId);
if (admin) {
return {
balance: 999999,
monthlyUsed: 0,
monthlyLimit: 999999,
plan: 'Admin',
remaining: 999999,
total: 999999,
isAdmin: true,
};
}
const transactions = await this.db.creditTransaction.findMany({
where: { userId },
orderBy: { createdAt: 'desc' },
@@ -182,6 +207,10 @@ export class BillingService {
balance,
monthlyUsed,
monthlyLimit,
plan: subscription?.plan?.displayName || 'Free',
remaining: balance,
total: monthlyLimit,
isAdmin: false,
};
}
@@ -189,6 +218,13 @@ export class BillingService {
* Kredi harca (video üretimi için)
*/
async spendCredits(userId: string, amount: number, projectId: string, description: string) {
// Admin bypass — sınırsız kredi
const admin = await this.isAdmin(userId);
if (admin) {
this.logger.log(`🛡️ Admin kredi bypass: ${amount} — User: ${userId}, Project: ${projectId}`);
return { id: 'admin-bypass', amount: -amount, type: 'usage', description };
}
const balance = await this.getCreditBalance(userId);
if (balance.balance < amount) {