generated from fahricansecer/boilerplate-be
This commit is contained in:
117
prisma/seed-admin.ts
Normal file
117
prisma/seed-admin.ts
Normal 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();
|
||||||
|
});
|
||||||
@@ -122,26 +122,61 @@ export class AdminService {
|
|||||||
|
|
||||||
// ── Proje ve Render Yönetimi ──────────────────────────────────────
|
// ── Proje ve Render Yönetimi ──────────────────────────────────────
|
||||||
|
|
||||||
async getAllProjects() {
|
async getAllProjects(params: { page: number; limit: number; status?: string; userId?: string }) {
|
||||||
return this.prisma.project.findMany({
|
const { page, limit, status, userId } = params;
|
||||||
include: { user: { select: { email: true, firstName: true, lastName: true } } },
|
|
||||||
orderBy: { createdAt: 'desc' },
|
// 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() {
|
async getAllRenderJobs(params: { page: number; limit: number; status?: string }) {
|
||||||
return this.prisma.renderJob.findMany({
|
const { page, limit, status } = params;
|
||||||
include: { project: { select: { name: true } } },
|
|
||||||
orderBy: { createdAt: 'desc' },
|
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 ────────────────────────────────────────────
|
// ── Kullanıcı Yönetimi ────────────────────────────────────────────
|
||||||
|
|
||||||
async banUser(userId: string, isBanned: boolean) {
|
async setUserActive(userId: string, isActive: boolean) {
|
||||||
return this.prisma.user.update({
|
return this.prisma.user.update({
|
||||||
where: { id: userId },
|
where: { id: userId },
|
||||||
data: { isActive: !isBanned },
|
data: { isActive },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,10 +149,35 @@ export class BillingService {
|
|||||||
return plans;
|
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
|
* Kullanıcı kredi bakiyesi
|
||||||
*/
|
*/
|
||||||
async getCreditBalance(userId: string) {
|
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({
|
const transactions = await this.db.creditTransaction.findMany({
|
||||||
where: { userId },
|
where: { userId },
|
||||||
orderBy: { createdAt: 'desc' },
|
orderBy: { createdAt: 'desc' },
|
||||||
@@ -182,6 +207,10 @@ export class BillingService {
|
|||||||
balance,
|
balance,
|
||||||
monthlyUsed,
|
monthlyUsed,
|
||||||
monthlyLimit,
|
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)
|
* Kredi harca (video üretimi için)
|
||||||
*/
|
*/
|
||||||
async spendCredits(userId: string, amount: number, projectId: string, description: string) {
|
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);
|
const balance = await this.getCreditBalance(userId);
|
||||||
|
|
||||||
if (balance.balance < amount) {
|
if (balance.balance < amount) {
|
||||||
|
|||||||
Reference in New Issue
Block a user