mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-11 20:05:25 +00:00
add get users and delete user endpoints
This commit is contained in:
parent
5b1caae854
commit
10969707bc
2 changed files with 174 additions and 0 deletions
93
packages/web/src/app/api/(server)/ee/user/route.ts
Normal file
93
packages/web/src/app/api/(server)/ee/user/route.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
'use server';
|
||||
|
||||
import { withAuthV2, withMinimumOrgRole } from "@/withAuthV2";
|
||||
import { OrgRole } from "@sourcebot/db";
|
||||
import { isServiceError } from "@/lib/utils";
|
||||
import { serviceErrorResponse, missingQueryParam, notFound } from "@/lib/serviceError";
|
||||
import { createLogger } from "@sourcebot/logger";
|
||||
import { NextRequest } from "next/server";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { ErrorCode } from "@/lib/errorCodes";
|
||||
import { getAuditService } from "@/ee/features/audit/factory";
|
||||
|
||||
const logger = createLogger('ee-user-api');
|
||||
const auditService = getAuditService();
|
||||
|
||||
export const DELETE = async (request: NextRequest) => {
|
||||
const url = new URL(request.url);
|
||||
const userId = url.searchParams.get('userId');
|
||||
|
||||
if (!userId) {
|
||||
return serviceErrorResponse(missingQueryParam('userId'));
|
||||
}
|
||||
|
||||
const result = await withAuthV2(async ({ org, role, user: currentUser, prisma }) => {
|
||||
return withMinimumOrgRole(role, OrgRole.OWNER, async () => {
|
||||
try {
|
||||
if (currentUser.id === userId) {
|
||||
return {
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
errorCode: ErrorCode.INVALID_REQUEST_BODY,
|
||||
message: 'Cannot delete your own user account',
|
||||
};
|
||||
}
|
||||
|
||||
const targetUser = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!targetUser) {
|
||||
return notFound('User not found');
|
||||
}
|
||||
|
||||
await auditService.createAudit({
|
||||
action: "user.delete",
|
||||
actor: {
|
||||
id: currentUser.id,
|
||||
type: "user"
|
||||
},
|
||||
target: {
|
||||
id: userId,
|
||||
type: "user"
|
||||
},
|
||||
orgId: org.id,
|
||||
});
|
||||
|
||||
// Delete the user (cascade will handle all related records)
|
||||
await prisma.user.delete({
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
});
|
||||
|
||||
logger.info('User deleted successfully', {
|
||||
deletedUserId: userId,
|
||||
deletedByUserId: currentUser.id,
|
||||
orgId: org.id
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'User deleted successfully'
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error deleting user', { error, userId });
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (isServiceError(result)) {
|
||||
return serviceErrorResponse(result);
|
||||
}
|
||||
|
||||
return Response.json(result, { status: StatusCodes.OK });
|
||||
};
|
||||
|
||||
81
packages/web/src/app/api/(server)/ee/users/route.ts
Normal file
81
packages/web/src/app/api/(server)/ee/users/route.ts
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
'use server';
|
||||
|
||||
import { withAuthV2, withMinimumOrgRole } from "@/withAuthV2";
|
||||
import { OrgRole } from "@sourcebot/db";
|
||||
import { isServiceError } from "@/lib/utils";
|
||||
import { serviceErrorResponse } from "@/lib/serviceError";
|
||||
import { createLogger } from "@sourcebot/logger";
|
||||
import { getAuditService } from "@/ee/features/audit/factory";
|
||||
|
||||
const logger = createLogger('ee-users-api');
|
||||
const auditService = getAuditService();
|
||||
|
||||
export const GET = async () => {
|
||||
const result = await withAuthV2(async ({ prisma, org, role, user }) => {
|
||||
return withMinimumOrgRole(role, OrgRole.OWNER, async () => {
|
||||
try {
|
||||
const memberships = await prisma.userToOrg.findMany({
|
||||
where: {
|
||||
orgId: org.id,
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
|
||||
const usersWithActivity = await Promise.all(
|
||||
memberships.map(async (membership) => {
|
||||
const lastActivity = await prisma.audit.findFirst({
|
||||
where: {
|
||||
actorId: membership.user.id,
|
||||
actorType: 'user',
|
||||
orgId: org.id,
|
||||
},
|
||||
orderBy: {
|
||||
timestamp: 'desc',
|
||||
},
|
||||
select: {
|
||||
timestamp: true,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
id: membership.user.id,
|
||||
name: membership.user.name,
|
||||
email: membership.user.email,
|
||||
role: membership.role,
|
||||
createdAt: membership.user.createdAt,
|
||||
lastActivityAt: lastActivity?.timestamp ?? null,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
await auditService.createAudit({
|
||||
action: "user.list",
|
||||
actor: {
|
||||
id: user.id,
|
||||
type: "user"
|
||||
},
|
||||
target: {
|
||||
id: org.id.toString(),
|
||||
type: "org"
|
||||
},
|
||||
orgId: org.id
|
||||
});
|
||||
|
||||
logger.info('Fetched users list', { count: usersWithActivity.length });
|
||||
return usersWithActivity;
|
||||
} catch (error) {
|
||||
logger.error('Error fetching users', { error });
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (isServiceError(result)) {
|
||||
return serviceErrorResponse(result);
|
||||
}
|
||||
|
||||
return Response.json(result);
|
||||
};
|
||||
|
||||
Loading…
Reference in a new issue