finalizing team support
This commit is contained in:
@@ -58,6 +58,12 @@ export default async function updateCollection(
|
||||
}
|
||||
}
|
||||
|
||||
const uniqueMembers = data.members.filter(
|
||||
(e, i, a) =>
|
||||
a.findIndex((el) => el.userId === e.userId) === i &&
|
||||
e.userId !== collectionIsAccessible.ownerId
|
||||
);
|
||||
|
||||
const updatedCollection = await prisma.$transaction(async () => {
|
||||
await prisma.usersAndCollections.deleteMany({
|
||||
where: {
|
||||
@@ -91,7 +97,7 @@ export default async function updateCollection(
|
||||
}
|
||||
: undefined,
|
||||
members: {
|
||||
create: data.members.map((e) => ({
|
||||
create: uniqueMembers.map((e) => ({
|
||||
user: { connect: { id: e.userId } },
|
||||
canCreate: e.canCreate,
|
||||
canUpdate: e.canUpdate,
|
||||
|
||||
@@ -5,13 +5,20 @@ export default async function getPublicUser(
|
||||
isId: boolean,
|
||||
requestingId?: number
|
||||
) {
|
||||
const user = await prisma.user.findUnique({
|
||||
const user = await prisma.user.findFirst({
|
||||
where: isId
|
||||
? {
|
||||
id: Number(targetId) as number,
|
||||
}
|
||||
: {
|
||||
username: targetId as string,
|
||||
OR: [
|
||||
{
|
||||
username: targetId as string,
|
||||
},
|
||||
{
|
||||
email: targetId as string,
|
||||
},
|
||||
],
|
||||
},
|
||||
include: {
|
||||
whitelistedUsers: {
|
||||
@@ -22,7 +29,7 @@ export default async function getPublicUser(
|
||||
},
|
||||
});
|
||||
|
||||
if (!user)
|
||||
if (!user || !user.id)
|
||||
return { response: "User not found or profile is private.", status: 404 };
|
||||
|
||||
const whitelistedUsernames = user.whitelistedUsers?.map(
|
||||
@@ -31,7 +38,7 @@ export default async function getPublicUser(
|
||||
|
||||
const isInAPublicCollection = await prisma.collection.findFirst({
|
||||
where: {
|
||||
["OR"]: [
|
||||
OR: [
|
||||
{ ownerId: user.id },
|
||||
{
|
||||
members: {
|
||||
@@ -73,6 +80,7 @@ export default async function getPublicUser(
|
||||
id: lessSensitiveInfo.id,
|
||||
name: lessSensitiveInfo.name,
|
||||
username: lessSensitiveInfo.username,
|
||||
email: lessSensitiveInfo.email,
|
||||
image: lessSensitiveInfo.image,
|
||||
archiveAsScreenshot: lessSensitiveInfo.archiveAsScreenshot,
|
||||
archiveAsMonolith: lessSensitiveInfo.archiveAsMonolith,
|
||||
|
||||
@@ -1,21 +1,71 @@
|
||||
import { prisma } from "@/lib/api/db";
|
||||
import { User } from "@prisma/client";
|
||||
|
||||
export default async function getUsers() {
|
||||
// Get all users
|
||||
const users = await prisma.user.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
emailVerified: true,
|
||||
subscriptions: {
|
||||
select: {
|
||||
active: true,
|
||||
export default async function getUsers(user: User) {
|
||||
if (user.id === Number(process.env.NEXT_PUBLIC_ADMIN || 1)) {
|
||||
const users = await prisma.user.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
emailVerified: true,
|
||||
subscriptions: {
|
||||
select: {
|
||||
active: true,
|
||||
},
|
||||
},
|
||||
createdAt: true,
|
||||
},
|
||||
createdAt: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return { response: users.sort((a: any, b: any) => a.id - b.id), status: 200 };
|
||||
return {
|
||||
response: users.sort((a: any, b: any) => a.id - b.id),
|
||||
status: 200,
|
||||
};
|
||||
} else {
|
||||
let subscriptionId = (
|
||||
await prisma.subscription.findFirst({
|
||||
where: {
|
||||
userId: user.id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
)?.id;
|
||||
|
||||
if (!subscriptionId)
|
||||
return {
|
||||
response: "Subscription not found.",
|
||||
status: 404,
|
||||
};
|
||||
|
||||
const users = await prisma.user.findMany({
|
||||
where: {
|
||||
OR: [
|
||||
{
|
||||
parentSubscriptionId: subscriptionId,
|
||||
},
|
||||
{
|
||||
subscriptions: {
|
||||
id: subscriptionId,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
username: true,
|
||||
email: true,
|
||||
emailVerified: true,
|
||||
createdAt: true,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
response: users.sort((a: any, b: any) => a.id - b.id),
|
||||
status: 200,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,19 @@ import removeFolder from "@/lib/api/storage/removeFolder";
|
||||
import Stripe from "stripe";
|
||||
import { DeleteUserBody } from "@/types/global";
|
||||
import removeFile from "@/lib/api/storage/removeFile";
|
||||
import updateSeats from "@/lib/api/stripe/updateSeats";
|
||||
|
||||
export default async function deleteUserById(
|
||||
userId: number,
|
||||
body: DeleteUserBody,
|
||||
isServerAdmin?: boolean
|
||||
isServerAdmin: boolean,
|
||||
queryId: number
|
||||
) {
|
||||
// First, we retrieve the user from the database
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
include: {
|
||||
subscriptions: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
@@ -23,21 +27,74 @@ export default async function deleteUserById(
|
||||
}
|
||||
|
||||
if (!isServerAdmin) {
|
||||
if (user.password) {
|
||||
const isPasswordValid = bcrypt.compareSync(body.password, user.password);
|
||||
if (queryId === userId) {
|
||||
if (user.password) {
|
||||
const isPasswordValid = bcrypt.compareSync(
|
||||
body.password,
|
||||
user.password
|
||||
);
|
||||
|
||||
if (!isPasswordValid && !isServerAdmin) {
|
||||
if (!isPasswordValid && !isServerAdmin) {
|
||||
return {
|
||||
response: "Invalid credentials.",
|
||||
status: 401,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
response: "Invalid credentials.",
|
||||
status: 401, // Unauthorized
|
||||
response:
|
||||
"User has no password. Please reset your password from the forgot password page.",
|
||||
status: 401,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
response:
|
||||
"User has no password. Please reset your password from the forgot password page.",
|
||||
status: 401, // Unauthorized
|
||||
};
|
||||
if (user.parentSubscriptionId) {
|
||||
console.log(userId, user.parentSubscriptionId);
|
||||
|
||||
return {
|
||||
response: "Permission denied.",
|
||||
status: 401,
|
||||
};
|
||||
} else {
|
||||
if (!user.subscriptions) {
|
||||
return {
|
||||
response: "User has no subscription.",
|
||||
status: 401,
|
||||
};
|
||||
}
|
||||
|
||||
const findChild = await prisma.user.findFirst({
|
||||
where: { id: queryId, parentSubscriptionId: user.subscriptions?.id },
|
||||
});
|
||||
|
||||
if (!findChild)
|
||||
return {
|
||||
response: "Permission denied.",
|
||||
status: 401,
|
||||
};
|
||||
|
||||
const removeUser = await prisma.user.update({
|
||||
where: { id: findChild.id },
|
||||
data: {
|
||||
parentSubscription: {
|
||||
disconnect: true,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
|
||||
await updateSeats(
|
||||
user.subscriptions.stripeSubscriptionId,
|
||||
user.subscriptions.quantity - 1
|
||||
);
|
||||
|
||||
return {
|
||||
response: removeUser,
|
||||
status: 200,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,27 +104,27 @@ export default async function deleteUserById(
|
||||
async (prisma) => {
|
||||
// Delete Access Tokens
|
||||
await prisma.accessToken.deleteMany({
|
||||
where: { userId },
|
||||
where: { userId: queryId },
|
||||
});
|
||||
|
||||
// Delete whitelisted users
|
||||
await prisma.whitelistedUser.deleteMany({
|
||||
where: { userId },
|
||||
where: { userId: queryId },
|
||||
});
|
||||
|
||||
// Delete links
|
||||
await prisma.link.deleteMany({
|
||||
where: { collection: { ownerId: userId } },
|
||||
where: { collection: { ownerId: queryId } },
|
||||
});
|
||||
|
||||
// Delete tags
|
||||
await prisma.tag.deleteMany({
|
||||
where: { ownerId: userId },
|
||||
where: { ownerId: queryId },
|
||||
});
|
||||
|
||||
// Find collections that the user owns
|
||||
const collections = await prisma.collection.findMany({
|
||||
where: { ownerId: userId },
|
||||
where: { ownerId: queryId },
|
||||
});
|
||||
|
||||
for (const collection of collections) {
|
||||
@@ -86,29 +143,29 @@ export default async function deleteUserById(
|
||||
|
||||
// Delete collections after cleaning up related data
|
||||
await prisma.collection.deleteMany({
|
||||
where: { ownerId: userId },
|
||||
where: { ownerId: queryId },
|
||||
});
|
||||
|
||||
// Delete subscription
|
||||
if (process.env.STRIPE_SECRET_KEY)
|
||||
await prisma.subscription
|
||||
.delete({
|
||||
where: { userId },
|
||||
where: { userId: queryId },
|
||||
})
|
||||
.catch((err) => console.log(err));
|
||||
|
||||
await prisma.usersAndCollections.deleteMany({
|
||||
where: {
|
||||
OR: [{ userId: userId }, { collection: { ownerId: userId } }],
|
||||
OR: [{ userId: queryId }, { collection: { ownerId: queryId } }],
|
||||
},
|
||||
});
|
||||
|
||||
// Delete user's avatar
|
||||
await removeFile({ filePath: `uploads/avatar/${userId}.jpg` });
|
||||
await removeFile({ filePath: `uploads/avatar/${queryId}.jpg` });
|
||||
|
||||
// Finally, delete the user
|
||||
await prisma.user.delete({
|
||||
where: { id: userId },
|
||||
where: { id: queryId },
|
||||
});
|
||||
},
|
||||
{ timeout: 20000 }
|
||||
|
||||
@@ -35,6 +35,7 @@ export default async function getUserById(userId: number) {
|
||||
whitelistedUsers: whitelistedUsernames,
|
||||
subscription: {
|
||||
active: subscriptions?.active,
|
||||
quantity: subscriptions?.quantity,
|
||||
},
|
||||
parentSubscription: {
|
||||
active: parentSubscription?.active,
|
||||
|
||||
@@ -277,6 +277,7 @@ export default async function updateUserById(
|
||||
image: userInfo.image ? `${userInfo.image}?${Date.now()}` : "",
|
||||
subscription: {
|
||||
active: subscriptions?.active,
|
||||
quantity: subscriptions?.quantity,
|
||||
},
|
||||
parentSubscription: {
|
||||
active: parentSubscription?.active,
|
||||
|
||||
Reference in New Issue
Block a user