165 lines
4.5 KiB
TypeScript
165 lines
4.5 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import { getServerSession } from 'next-auth';
|
|
import { authOptions } from '@/lib/auth';
|
|
import { prisma } from '@/lib/prisma';
|
|
import { logger } from '@/lib/logger';
|
|
|
|
export async function POST(
|
|
request: Request,
|
|
props: { params: Promise<{ missionId: string }> }
|
|
) {
|
|
const params = await props.params;
|
|
const { missionId } = params;
|
|
|
|
try {
|
|
// Check authentication
|
|
const session = await getServerSession(authOptions);
|
|
if (!session?.user?.id) {
|
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
}
|
|
|
|
const body = await request.json();
|
|
const { guardianRole, oldUserId, newUserId, oldUserEmail, newUserEmail } = body;
|
|
|
|
if (!guardianRole || !newUserId) {
|
|
return NextResponse.json(
|
|
{ error: 'guardianRole and newUserId are required' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Get mission details
|
|
const mission = await prisma.mission.findUnique({
|
|
where: { id: missionId },
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
creatorId: true,
|
|
leantimeProjectId: true,
|
|
outlineCollectionId: true,
|
|
rocketChatChannelId: true,
|
|
giteaRepositoryUrl: true,
|
|
},
|
|
});
|
|
|
|
if (!mission) {
|
|
return NextResponse.json({ error: 'Mission not found' }, { status: 404 });
|
|
}
|
|
|
|
// Check if user is authorized (creator or admin)
|
|
const isCreator = mission.creatorId === session.user.id;
|
|
const isAdmin = session.user.role?.includes('admin');
|
|
|
|
if (!isCreator && !isAdmin) {
|
|
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
|
}
|
|
|
|
// Map guardian role to database role
|
|
const roleMap: Record<string, string> = {
|
|
'temps': 'temps',
|
|
'parole': 'parole',
|
|
'memoire': 'memoire',
|
|
};
|
|
|
|
const dbRole = roleMap[guardianRole];
|
|
if (!dbRole) {
|
|
return NextResponse.json({ error: 'Invalid guardian role' }, { status: 400 });
|
|
}
|
|
|
|
// Update the guardian in database
|
|
// First, remove old guardian if exists
|
|
if (oldUserId) {
|
|
await prisma.missionUser.deleteMany({
|
|
where: {
|
|
missionId,
|
|
userId: oldUserId,
|
|
role: dbRole,
|
|
},
|
|
});
|
|
}
|
|
|
|
// Then add new guardian
|
|
await prisma.missionUser.create({
|
|
data: {
|
|
missionId,
|
|
userId: newUserId,
|
|
role: dbRole,
|
|
},
|
|
});
|
|
|
|
// Extract repo name from Gitea URL
|
|
let repoName = '';
|
|
if (mission.giteaRepositoryUrl) {
|
|
try {
|
|
const url = new URL(mission.giteaRepositoryUrl);
|
|
const pathParts = url.pathname.split('/').filter(Boolean);
|
|
repoName = pathParts[pathParts.length - 1] || '';
|
|
} catch {
|
|
const match = mission.giteaRepositoryUrl.match(/\/([^\/]+)\/?$/);
|
|
repoName = match ? match[1] : '';
|
|
}
|
|
}
|
|
|
|
// Prepare data for N8N webhook
|
|
const n8nData = {
|
|
missionId: mission.id,
|
|
missionName: mission.name,
|
|
guardianRole,
|
|
oldUserId,
|
|
newUserId,
|
|
oldUserEmail,
|
|
newUserEmail,
|
|
repoName,
|
|
leantimeProjectId: mission.leantimeProjectId || '',
|
|
outlineCollectionId: mission.outlineCollectionId || '',
|
|
rocketChatChannelId: mission.rocketChatChannelId || '',
|
|
giteaRepositoryUrl: mission.giteaRepositoryUrl || '',
|
|
};
|
|
|
|
// Call N8N webhook
|
|
const webhookUrl = process.env.N8N_CHANGE_GUARDIAN_WEBHOOK_URL || 'https://brain.slm-lab.net/webhook/NeahMissionChangeGuardian';
|
|
const apiKey = process.env.N8N_API_KEY || '';
|
|
|
|
logger.debug('Calling N8N ChangeGuardian webhook', {
|
|
missionId,
|
|
guardianRole,
|
|
oldUserId,
|
|
newUserId,
|
|
});
|
|
|
|
const response = await fetch(webhookUrl, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'x-api-key': apiKey,
|
|
},
|
|
body: JSON.stringify(n8nData),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorText = await response.text();
|
|
logger.error('N8N ChangeGuardian webhook error', {
|
|
status: response.status,
|
|
error: errorText.substring(0, 200),
|
|
});
|
|
// Continue even if N8N fails, database is already updated
|
|
}
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
message: 'Guardian changed successfully',
|
|
});
|
|
|
|
} catch (error) {
|
|
logger.error('Error changing guardian', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
missionId,
|
|
});
|
|
return NextResponse.json(
|
|
{ error: 'Failed to change guardian', details: error instanceof Error ? error.message : String(error) },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|