DeeCeeXxx's picture
Upload 114 files
e9d5b7d verified
"use server";
import { getDb } from "@/lib/mongodb";
import { getLoggedInUser, logoutUser } from "@/lib/actions/auth";
import bcrypt from 'bcryptjs';
import { differenceInHours } from 'date-fns';
import type { User, Deployment } from "@/lib/types";
import type { TransferCoinsInput, ChangePasswordInput, UpdateProfileInput, DeleteAccountInput } from "@/lib/schemas";
import { revalidatePath } from 'next/cache';
const DAILY_COIN_AMOUNT = 10;
const CLAIM_COOLDOWN_HOURS = 24;
export async function claimDailyCoins(): Promise<{ success: boolean; message: string; newBalance?: number; nextClaimAvailableInMs?: number }> {
const user = await getLoggedInUser();
if (!user) {
return { success: false, message: "You must be logged in to claim coins." };
}
const now = new Date();
if (user.lastCoinClaim) {
const hoursSinceLastClaim = differenceInHours(now, new Date(user.lastCoinClaim));
if (hoursSinceLastClaim < CLAIM_COOLDOWN_HOURS) {
const nextClaimTime = new Date(user.lastCoinClaim).getTime() + CLAIM_COOLDOWN_HOURS * 60 * 60 * 1000;
const nextClaimAvailableInMs = Math.max(0, nextClaimTime - now.getTime());
return {
success: false,
message: `You can claim again in ${CLAIM_COOLDOWN_HOURS - hoursSinceLastClaim} hour(s).`,
nextClaimAvailableInMs
};
}
}
try {
const db = await getDb();
const usersCollection = db.collection<User>("users");
// Query by string _id directly
const updatedUserResult = await usersCollection.findOneAndUpdate(
{ _id: user._id },
{
$inc: { coins: DAILY_COIN_AMOUNT },
$set: { lastCoinClaim: now }
},
{ returnDocument: "after" }
);
if (!updatedUserResult) {
return { success: false, message: "Failed to update user balance. User not found or update failed." };
}
revalidatePath("/dashboard");
return {
success: true,
message: `Successfully claimed ${DAILY_COIN_AMOUNT} coins!`,
newBalance: updatedUserResult.coins,
nextClaimAvailableInMs: CLAIM_COOLDOWN_HOURS * 60 * 60 * 1000
};
} catch (error) {
console.error("Error claiming daily coins:", error);
return { success: false, message: "An unexpected error occurred." };
}
}
export async function transferCoins(data: TransferCoinsInput): Promise<{ success: boolean; message: string; newSenderBalance?: number }> {
const sender = await getLoggedInUser();
if (!sender) {
return { success: false, message: "You must be logged in to transfer coins." };
}
if (data.amount <= 0) {
return { success: false, message: "Transfer amount must be positive." };
}
if (sender.coins < data.amount && sender.role !== 'admin') {
return { success: false, message: "Insufficient coin balance." };
}
if (sender.email === data.recipientEmail) {
return { success: false, message: "You cannot transfer coins to yourself." };
}
try {
const db = await getDb();
const usersCollection = db.collection<User>("users");
const recipient = await usersCollection.findOne({ email: data.recipientEmail });
if (!recipient) {
return { success: false, message: "Recipient user not found." };
}
if (sender.role !== 'admin') {
// Query by string _id directly
const freshSenderData = await usersCollection.findOne({ _id: sender._id });
if (!freshSenderData || freshSenderData.coins < data.amount) {
return { success: false, message: "Insufficient coin balance. Please refresh and try again." };
}
}
const senderUpdateResult = await usersCollection.updateOne(
{ _id: sender._id }, // Query by string _id
{ $inc: { coins: -data.amount } }
);
if (senderUpdateResult.modifiedCount === 0) {
if (sender.role !== 'admin') {
return { success: false, message: "Failed to update your balance. Please try again." };
}
}
const recipientUpdateResult = await usersCollection.updateOne(
{ _id: recipient._id }, // Query by string _id
{ $inc: { coins: data.amount } }
);
if (recipientUpdateResult.modifiedCount === 0) {
// Rollback sender's coins if recipient update failed
await usersCollection.updateOne(
{ _id: sender._id }, // Query by string _id
{ $inc: { coins: data.amount } }
);
return { success: false, message: "Failed to transfer coins to recipient. Your balance has been restored." };
}
const newSenderData = await usersCollection.findOne({ _id: sender._id }); // Query by string _id
revalidatePath("/dashboard");
return {
success: true,
message: `Successfully transferred ${data.amount} coins to ${recipient.name}.`,
newSenderBalance: newSenderData?.coins ?? sender.coins - data.amount,
};
} catch (error) {
console.error("Error transferring coins:", error);
return { success: false, message: "An unexpected error occurred during the transfer." };
}
}
export async function updateProfile(data: UpdateProfileInput): Promise<{ success: boolean; message: string }> {
const loggedInUser = await getLoggedInUser();
if (!loggedInUser) {
return { success: false, message: "You must be logged in to update your profile." };
}
try {
const db = await getDb();
const usersCollection = db.collection<User>("users");
const result = await usersCollection.updateOne(
{ _id: loggedInUser._id }, // Query by string _id
{ $set: { name: data.name } }
);
if (result.modifiedCount === 0 && result.matchedCount > 0) {
return { success: true, message: "No changes detected in profile information." };
}
if (result.modifiedCount === 0) {
return { success: false, message: "Failed to update profile. User not found." };
}
revalidatePath('/dashboard/profile');
revalidatePath('/dashboard');
return { success: true, message: "Profile updated successfully." };
} catch (error) {
console.error("Error updating profile:", error);
return { success: false, message: "An unexpected error occurred while updating profile." };
}
}
export async function changePassword(data: ChangePasswordInput): Promise<{ success: boolean; message: string }> {
const loggedInUser = await getLoggedInUser();
if (!loggedInUser) {
return { success: false, message: "You must be logged in to change your password." };
}
try {
const db = await getDb();
const usersCollection = db.collection<User>("users");
const userFromDb = await usersCollection.findOne({ _id: loggedInUser._id }); // Query by string _id
if (!userFromDb) {
return { success: false, message: "User not found." };
}
const isCurrentPasswordValid = await bcrypt.compare(data.currentPassword, userFromDb.passwordHash);
if (!isCurrentPasswordValid) {
return { success: false, message: "Incorrect current password." };
}
const newPasswordHash = await bcrypt.hash(data.newPassword, 10);
await usersCollection.updateOne(
{ _id: loggedInUser._id }, // Query by string _id
{ $set: { passwordHash: newPasswordHash } }
);
return { success: true, message: "Password changed successfully." };
} catch (error) {
console.error("Error changing password:", error);
return { success: false, message: "An unexpected error occurred while changing password." };
}
}
export async function deleteUserAccount(data: DeleteAccountInput): Promise<{ success: boolean; message: string }> {
const loggedInUser = await getLoggedInUser();
if (!loggedInUser) {
return { success: false, message: "You must be logged in to delete your account." };
}
try {
const db = await getDb();
const usersCollection = db.collection<User>("users");
const deploymentsCollection = db.collection<Deployment>("deployments");
const userFromDb = await usersCollection.findOne({ _id: loggedInUser._id }); // Query by string _id
if (!userFromDb) {
return { success: false, message: "User not found." };
}
const isCurrentPasswordValid = await bcrypt.compare(data.currentPassword, userFromDb.passwordHash);
if (!isCurrentPasswordValid) {
return { success: false, message: "Incorrect password. Account deletion failed." };
}
if (userFromDb.role === 'admin') {
const adminCount = await usersCollection.countDocuments({ role: 'admin' });
if (adminCount <= 1) {
return { success: false, message: "Cannot delete the last admin account. Promote another user to admin first." };
}
}
await deploymentsCollection.deleteMany({ userId: loggedInUser._id }); // Query by string _id
const deleteResult = await usersCollection.deleteOne({ _id: loggedInUser._id }); // Query by string _id
if (deleteResult.deletedCount === 0) {
return { success: false, message: "Failed to delete user account from the database." };
}
await logoutUser();
return { success: true, message: "Account and associated deployments deleted successfully. You have been logged out." };
} catch (error) {
console.error("Error deleting account:", error);
if (error instanceof Error && error.message.includes('NEXT_REDIRECT')) {
throw error;
}
return { success: false, message: "An unexpected error occurred while deleting your account." };
}
}