admin role enhancment
basic invitation flow
This commit is contained in:
1 parent
d112dbb122
commit
b1f01208fa
6 files changed
+59
-13
No files matched your search
@@ -84,12 +84,30 @@ export async function POST(request: NextRequest) {
|
||||
if (data.sendInvitation && data.email) {
|
||||
try {
|
||||
const client = await clerkClient();
|
||||
|
||||
// Build publicMetadata - only include gymId if it exists
|
||||
const publicMetadata: Record<string, any> = {
|
||||
role: data.role,
|
||||
};
|
||||
if (assignedGymId) {
|
||||
publicMetadata.gymId = assignedGymId;
|
||||
}
|
||||
|
||||
// Determine redirect URL based on role
|
||||
// Staff (admin, trainer, superAdmin) → Admin web app
|
||||
// Clients → Mobile app (handled by Clerk's default)
|
||||
const isStaffRole = ["admin", "trainer", "superAdmin"].includes(
|
||||
data.role,
|
||||
);
|
||||
const redirectUrl = isStaffRole
|
||||
? `${process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/sign-up`
|
||||
: undefined; // Clients use default Clerk redirect
|
||||
|
||||
const invitation = await client.invitations.createInvitation({
|
||||
emailAddress: data.email,
|
||||
publicMetadata: {
|
||||
role: data.role,
|
||||
gymId: assignedGymId,
|
||||
},
|
||||
publicMetadata,
|
||||
redirectUrl,
|
||||
ignoreExisting: true, // Don't fail if invitation already exists
|
||||
});
|
||||
|
||||
log.info("Clerk invitation sent", {
|
||||
@@ -97,6 +115,7 @@ export async function POST(request: NextRequest) {
|
||||
role: data.role,
|
||||
gymId: assignedGymId,
|
||||
invitationId: invitation.id,
|
||||
redirectUrl: redirectUrl || "default (mobile app)",
|
||||
});
|
||||
|
||||
// Send custom invitation email (in addition to Clerk's)
|
||||
@@ -117,7 +136,22 @@ export async function POST(request: NextRequest) {
|
||||
} catch (error: unknown) {
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : "Unknown error";
|
||||
log.error("Failed to send Clerk invitation", error);
|
||||
|
||||
// Extract Clerk-specific error details
|
||||
const clerkError = error as any;
|
||||
|
||||
log.error("Failed to send Clerk invitation", error, {
|
||||
email: data.email,
|
||||
role: data.role,
|
||||
gymId: assignedGymId,
|
||||
publicMetadata: assignedGymId
|
||||
? { role: data.role, gymId: assignedGymId }
|
||||
: { role: data.role },
|
||||
clerkStatus: clerkError?.status,
|
||||
clerkErrors: clerkError?.errors,
|
||||
clerkTraceId: clerkError?.clerkTraceId,
|
||||
});
|
||||
|
||||
return errorResponse(`Failed to send invitation: ${errorMessage}`, {
|
||||
status: 500,
|
||||
});
|
||||
|
||||
@@ -414,14 +414,15 @@ export async function PUT(request: NextRequest) {
|
||||
return forbiddenResponse(`Not authorized to assign role '${role}'`);
|
||||
}
|
||||
|
||||
// Authorization: trainers cannot reassign users to different gyms
|
||||
// Authorization: trainers and admins cannot reassign users to different gyms
|
||||
// Only superAdmins can reassign gyms
|
||||
if (
|
||||
requesterRole === "trainer" &&
|
||||
requesterRole !== "superAdmin" &&
|
||||
gymId !== undefined &&
|
||||
gymId !== existingUser.gymId
|
||||
) {
|
||||
return forbiddenResponse(
|
||||
"Trainers cannot reassign users to different gyms",
|
||||
"Only superAdmins can reassign users to different gyms",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user