Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

APIにPUT,DELETEを作成した #76

Merged
merged 4 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ API is provided by Firebase Cloud Functions. Database is provided by Firestore.
- Body
- name: string
- streak?: number
- example
- Example
```json
{
"name": "testUser",
Expand Down Expand Up @@ -147,7 +147,7 @@ the same as Get User Data by User Id
- userId: string
- deadline: Date
- text: string
- example
- Example
```json
{
"userId": "IK0Zc2hoUYaYjXoqzmCl",
Expand Down
18 changes: 3 additions & 15 deletions functions/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
/**
* Import function triggers from their respective submodules:
*
* import {onCall} from "firebase-functions/v2/https";
* import {onDocumentWritten} from "firebase-functions/v2/firestore";
*
* See a full list of supported triggers at https://firebase.google.com/docs/functions
*/

import cors from "cors";
import express from "express";
import rateLimit from "express-rate-limit";

Check warning on line 3 in functions/src/index.ts

View workflow job for this annotation

GitHub Actions / lint-check-functions

Using exported name 'rateLimit' as identifier for default import
import admin from "firebase-admin";
import * as logger from "firebase-functions/logger";
import { onRequest } from "firebase-functions/v2/https";
import helmet from "helmet";
import serviceAccount from "./serviceAccountKey.json";

// Start writing functions
// https://firebase.google.com/docs/functions/typescript

admin.initializeApp({
credential: admin.credential.cert(serviceAccount as admin.ServiceAccount),
storageBucket: "todo-real-c28fa.appspot.com",
Expand All @@ -33,15 +21,15 @@
// 10分間で最大300回に制限
app.use(
rateLimit({
windowMs: 5 * 60 * 1000,
windowMs: 10 * 60 * 1000,
max: 1000,
})
);
// 1時間で最大1000回に制限
app.use(
rateLimit({
windowMs: 10 * 60 * 1000,
max: 20,
windowMs: 60 * 60 * 1000,
max: 1000,
})
);

Expand Down
51 changes: 48 additions & 3 deletions functions/src/routers/goalRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface Goal {
}

// GET: 全ての目標を取得
router.route("/").get(async (req: Request, res: Response) => {
router.get("/", async (req: Request, res: Response) => {
try {
const goalSnapshot = await db.collection("goal").get();
if (goalSnapshot.empty) {
Expand All @@ -30,7 +30,7 @@ router.route("/").get(async (req: Request, res: Response) => {
});

// GET: userIdから目標を取得
router.route("/:userId").get(async (req: Request, res: Response) => {
router.get("/:userId", async (req: Request, res: Response) => {
const userId = req.params.userId;

if (!userId) {
Expand Down Expand Up @@ -59,7 +59,7 @@ router.route("/:userId").get(async (req: Request, res: Response) => {
});

// POST: 新しい目標を作成
router.route("/").post(async (req: Request, res: Response) => {
router.post("/", async (req: Request, res: Response) => {
const goalId = db.collection("goal").doc().id; // FirebaseのドキュメントIDを生成

let userId: Goal["userId"];
Expand Down Expand Up @@ -97,4 +97,49 @@ router.route("/").post(async (req: Request, res: Response) => {
}
});

// PUT: 目標を更新
router.put("/:goalId", async (req: Request, res: Response) => {
const goalId = req.params.goalId;
const { userId, deadline, text }: Partial<Goal> = req.body;

if (!userId && !deadline && !text) {
return res.status(400).json({
message: "At least one of userId, deadline, or text is required",
});
}

const updateData: Partial<Omit<Goal, "deadline">> & {
deadline?: admin.firestore.Timestamp;
} = {}; // 型エラーが出たため書き方変更
Comment on lines +111 to +113
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確かにDate型とadmin.firestore.Timestamp型で一致しなくなってしまうので、これでOKです!

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Takumi0216
7c3a5a2

修正コミット入れました、別のブランチがマージ待機してるのでマージしちゃいます~、もし何か忘れてたとかがあれば言ってもらえれば別PRでの追加 or revertで対応するので気軽に言ってください~

if (userId) updateData.userId = userId;
if (deadline)
updateData.deadline = admin.firestore.Timestamp.fromDate(
new Date(deadline)
);
if (text) updateData.text = text;

try {
await db.collection("goal").doc(goalId).update(updateData);
return res.json({ message: "Goal updated successfully", goalId });
} catch (error) {
return res.status(500).json({ message: "Error updating goal", error });
}
});

// DELETE: 目標を削除
router.delete("/:goalId", async (req: Request, res: Response) => {
const goalId = req.params.goalId;

if (!goalId) {
return res.status(400).json({ message: "Goal ID is required" });
}

try {
await db.collection("goal").doc(goalId).delete();
return res.json({ message: "Goal deleted successfully", goalId });
} catch (error) {
return res.status(500).json({ message: "Error deleting goal", error });
}
});

export default router;
41 changes: 41 additions & 0 deletions functions/src/routers/postRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,45 @@ router.post("/", async (req: Request, res: Response) => {
}
});

// PUT: 投稿を更新
router.put("/:postId", async (req: Request, res: Response) => {
const postId = req.params.postId;
const { userId, storeId, text, goalId }: Partial<Post> = req.body;

if (!userId && !storeId && !text && !goalId) {
return res
.status(400)
.json({ message: "At least one field is required to update" });
}

const updateData: Partial<Post> = {};
if (userId) updateData.userId = userId;
if (storeId) updateData.storeId = storeId;
if (text) updateData.text = text;
if (goalId) updateData.goalId = goalId;

try {
await db.collection("post").doc(postId).update(updateData);
return res.json({ message: "Post updated successfully", postId });
} catch (error) {
return res.status(500).json({ message: "Error updating post", error });
}
});

// DELETE: 投稿を削除
router.delete("/:postId", async (req: Request, res: Response) => {
const postId = req.params.postId;

if (!postId) {
return res.status(400).json({ message: "Post ID is required" });
}

try {
await db.collection("post").doc(postId).delete();
return res.json({ message: "Post deleted successfully", postId });
} catch (error) {
return res.status(500).json({ message: "Error deleting post", error });
}
});

export default router;
51 changes: 45 additions & 6 deletions functions/src/routers/userRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface User {
}

// GET: 全てのユーザーデータを取得(アカウント機能を作成したら廃止)
router.route("/").get(async (req: Request, res: Response) => {
router.get("/", async (req: Request, res: Response) => {
try {
const userSnapshot = await db.collection("user").get();

Expand All @@ -30,7 +30,7 @@ router.route("/").get(async (req: Request, res: Response) => {
});

// GET: userIdからユーザー情報を取得
router.route("/id/:userId").get(async (req: Request, res: Response) => {
router.get("/id/:userId", async (req: Request, res: Response) => {
const userId = req.params.userId;

if (!userId) {
Expand All @@ -49,7 +49,7 @@ router.route("/id/:userId").get(async (req: Request, res: Response) => {
});

// GET: userNameからユーザー情報を取得
router.route("/name/:userName").get(async (req: Request, res: Response) => {
router.get("/name/:userName", async (req: Request, res: Response) => {
const userName = req.params.userName;

if (!userName) {
Expand All @@ -74,7 +74,7 @@ router.route("/name/:userName").get(async (req: Request, res: Response) => {
});

// POST: 新しいユーザーを登録
router.route("/").post(async (req: Request, res: Response) => {
router.post("/", async (req: Request, res: Response) => {
let name: User["name"];
let uid: string;
let streak: User["streak"];
Expand All @@ -85,8 +85,8 @@ router.route("/").post(async (req: Request, res: Response) => {
return res.status(400).json({ message: "Invalid request body", error });
}

if (!name || !uid || streak === undefined) {
return res.status(400).json({ message: "name and streak are required" });
if (!name || !uid) {
return res.status(400).json({ message: "name and uid are required" });
}

// 既に同じ名前のuserが存在する場合はエラーを返す
Expand All @@ -111,6 +111,45 @@ router.route("/").post(async (req: Request, res: Response) => {
}
});

// PUT: ユーザー情報を更新
router.put("/:userId", async (req: Request, res: Response) => {
const userId = req.params.userId;
const { name, streak }: Partial<User> = req.body;

if (!name && streak === undefined) {
return res
.status(400)
.json({ message: "At least one of name or streak is required" });
}

const updateData: Partial<User> = {};
if (name) updateData.name = name;
if (streak !== undefined) updateData.streak = streak;

try {
await db.collection("user").doc(userId).update(updateData);
return res.json({ message: "User updated successfully", userId });
} catch (error) {
return res.status(500).json({ message: "Error updating user", error });
}
});

// DELETE: ユーザーを削除
router.delete("/:userId", async (req: Request, res: Response) => {
const userId = req.params.userId;

if (!userId) {
return res.status(400).json({ message: "User ID is required" });
}

try {
await db.collection("user").doc(userId).delete();
return res.json({ message: "User deleted successfully", userId });
} catch (error) {
return res.status(500).json({ message: "Error deleting user", error });
}
});

export default router;

// ユーザー名からユーザー情報を取得
Expand Down
3 changes: 2 additions & 1 deletion src/Components/PostForm/PostForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ export default function PostForm() {
}

setProgress(100); // アップロード完了の進捗を表示
console.log("success:", postData);
const data = await response.json();
console.log("Success:", data);
} catch (err) {
setError("データの送信に失敗しました");
console.error(err);
Expand Down
1 change: 0 additions & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export default function Top() {
return (
<>
<Posts />
asdf
<PostForm />
<GoalModal />
<Button variant="contained" onClick={requestPermission}>
Expand Down