Skip to content

Commit

Permalink
Merge branch 'dev' into jeehyun
Browse files Browse the repository at this point in the history
  • Loading branch information
hanj33 authored Dec 20, 2024
2 parents 0f22f5f + 220f4b3 commit 65542f6
Show file tree
Hide file tree
Showing 35 changed files with 1,394 additions and 312 deletions.
13 changes: 7 additions & 6 deletions src/app/api/auth/check-email/route.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// app/api/auth/check-email/route.js
import { auth } from "@/lib/firebaseAdmin";
import { db } from "@/lib/firebaseAdmin";
import { NextResponse } from "next/server";

export async function POST(req) {
Expand All @@ -14,13 +14,14 @@ export async function POST(req) {
}

try {
const userRecord = await auth.getUserByEmail(email);
const usersSnapshot = await db
.collection("users")
.where("email", "==", email)
.limit(1)
.get();

return NextResponse.json({ exists: userRecord.emailVerified });
return NextResponse.json({ exists: !usersSnapshot.empty });
} catch (error) {
if (error.code === "auth/user-not-found") {
return NextResponse.json({ exists: false });
}
console.error("Error in check-email:", error);
return NextResponse.json(
{ error: "이메일 확인 중 오류가 발생했습니다." },
Expand Down
114 changes: 114 additions & 0 deletions src/app/api/auth/reset-password/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { db } from "@/lib/firebaseAdmin";
import { getAuth } from "firebase-admin/auth";
import { Timestamp } from "firebase-admin/firestore";

function validatePassword(password) {
const minLength = 6;
const maxLength = 4096;
const hasUpperCase = /[A-Z]/.test(password);
const hasLowerCase = /[a-z]/.test(password);
const hasNumber = /[0-9]/.test(password);
const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(password);
const isValidLength =
password.length >= minLength && password.length <= maxLength;

return (
hasUpperCase && hasLowerCase && hasNumber && hasSpecialChar && isValidLength
);
}

export async function PUT(req) {
try {
const { email, code, newPassword } = await req.json();

// 비밀번호 유효성 검사
if (!validatePassword(newPassword)) {
return Response.json(
{
error: "비밀번호는 최소 8자 이상이며, 문자와 숫자를 포함해야 합니다.",
},
{ status: 400 }
);
}

// 가장 최근의 인증 코드 조회
const codesSnapshot = await db
.collection("verification_codes")
.where("email", "==", email)
.where("verified", "==", false)
.orderBy("createdAt", "desc")
.limit(1)
.get();

if (codesSnapshot.empty) {
return Response.json(
{ error: "유효하지 않은 인증 코드입니다." },
{ status: 400 }
);
}

const verificationDoc = codesSnapshot.docs[0];
const verificationData = verificationDoc.data();

// 만료 확인
if (verificationData.expiresAt.toMillis() < Date.now()) {
return Response.json(
{ error: "만료된 인증 코드입니다." },
{ status: 400 }
);
}

// 시도 횟수 확인
if (verificationData.attempts >= 5) {
return Response.json(
{ error: "최대 시도 횟수를 초과했습니다." },
{ status: 400 }
);
}

// 코드 확인
if (verificationData.code !== code) {
await verificationDoc.ref.update({
attempts: FieldValue.increment(1),
});
return Response.json(
{ error: "잘못된 인증 코드입니다." },
{ status: 400 }
);
}

// Firebase Auth에서 사용자 찾기
const auth = getAuth();
const userRecord = await auth.getUserByEmail(email);

// 비밀번호 변경
await auth.updateUser(userRecord.uid, {
password: newPassword,
});

// 인증 코드를 verified로 표시
await verificationDoc.ref.update({
verified: true,
verifiedAt: Timestamp.now(),
});

return Response.json({
success: true,
message: "비밀번호가 성공적으로 변경되었습니다.",
});
} catch (error) {
console.error("비밀번호 재설정 오류:", error);

if (error.code === "auth/invalid-password") {
return Response.json(
{ error: "유효하지 않은 비밀번호 형식입니다." },
{ status: 400 }
);
}

return Response.json(
{ error: "비밀번호 재설정 중 오류가 발생했습니다." },
{ status: 500 }
);
}
}
20 changes: 14 additions & 6 deletions src/app/api/post/feeds/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,17 @@ export async function GET(request) {
.map((doc) => {
const postData = doc.data();

const commentsLength = postData.comments
? postData.comments.filter((comment) => !comment.isDeleted).length
: 0;

// 점수 계산
const followScore = followingUids.includes(postData.authorUid)
? 30
: 0;
const interactionScore = Math.min(
30,
((postData.sparkCount || 0) + (postData.commentsCount || 0)) / 2
((postData.sparkCount || 0) + (commentsLength || 0)) / 2
);
const genreMatchScore = Math.min(
25,
Expand All @@ -166,7 +170,7 @@ export async function GET(request) {
const timeFreshnessScore = calculateTimeDecay(
postData.createdAt,
postData.sparkCount,
postData.commentsCount
commentsLength
);

const totalScore =
Expand All @@ -182,7 +186,7 @@ export async function GET(request) {
authorUid: postData.authorUid,
createdAt: postData.createdAt.toDate().toISOString(),
sparkCount: postData.sparkCount || 0,
commentsCount: postData.commentsCount || 0,
commentsCount: commentsLength || 0,
dreamGenres: postData.dreamGenres || [],
dreamMoods: postData.dreamMoods || [],
imageUrls: postData.imageUrls || [],
Expand Down Expand Up @@ -311,13 +315,17 @@ export async function GET(request) {
.map((doc) => {
const postData = doc.data();

const commentsLength = postData.comments
? postData.comments.filter((comment) => !comment.isDeleted).length
: 0;

// 점수 계산
const followScore = followingUids.includes(postData.authorUid)
? 30
: 0;
const interactionScore = Math.min(
30,
((postData.sparkCount || 0) + (postData.commentsCount || 0)) / 2
((postData.sparkCount || 0) + (commentsLength || 0)) / 2
);
const genreMatchScore = Math.min(
25,
Expand All @@ -329,7 +337,7 @@ export async function GET(request) {
const timeFreshnessScore = calculateTimeDecay(
postData.createdAt,
postData.sparkCount,
postData.commentsCount
commentsLength
);

const totalScore =
Expand All @@ -346,7 +354,7 @@ export async function GET(request) {
authorUid: postData.authorUid,
createdAt: postData.createdAt.toDate().toISOString(),
sparkCount: postData.sparkCount || 0,
commentsCount: postData.commentsCount || 0,
commentsCount: commentsLength || 0,
dreamGenres: postData.dreamGenres || [],
dreamMoods: postData.dreamMoods || [],
imageUrls: postData.imageUrls || [],
Expand Down
8 changes: 6 additions & 2 deletions src/app/api/post/read/[userId]/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ export async function GET(request, { params }) {
const postData = doc.data();
lastVisible = doc.id;

const commentsLength = postData.comments
? postData.comments.filter((comment) => !comment.isDeleted).length
: 0;

// summary 모드일 때는 요약 정보만 포함
if (summary) {
posts.push({
Expand All @@ -132,7 +136,7 @@ export async function GET(request, { params }) {
Array.isArray(postData.spark) && userUid
? postData.spark.includes(userUid)
: false,
commentsCount: postData.commentsCount || 0,
commentsCount: commentsLength || 0,
createdAt: postData.createdAt?.toDate().toISOString(),
updatedAt: postData.updatedAt?.toDate().toISOString(),
isTomong: postData.tomong
Expand All @@ -155,7 +159,7 @@ export async function GET(request, { params }) {
isPrivate: postData.isPrivate,
sparkCount: postData.sparkCount,
comments: postData.comments ? postData.comments : [],
commentsCount: postData.commentsCount,
commentsCount: commentsLength,
dreamGenres: postData.dreamGenres,
dreamMoods: postData.dreamMoods,
dreamRating: postData.dreamRating,
Expand Down
6 changes: 5 additions & 1 deletion src/app/api/post/search/[postId]/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export async function GET(request, { params }) {

const postData = postDoc.data();

const commentsLength = postData.comments
? postData.comments.filter((comment) => !comment.isDeleted).length
: 0;

// 삭제된 게시글 체크
if (postData.isDeleted) {
return NextResponse.json(
Expand Down Expand Up @@ -111,7 +115,7 @@ export async function GET(request, { params }) {
hasUserSparked: hasUserSparked,
sparkCount: postData.sparkCount,
comments: [],
commentsCount: postData.commentsCount,
commentsCount: commentsLength,
dreamGenres: postData.dreamGenres,
dreamMoods: postData.dreamMoods,
dreamRating: postData.dreamRating,
Expand Down
Loading

0 comments on commit 65542f6

Please sign in to comment.