0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Day24 — 投稿編集・削除APIを実装し、権限制御を入れる

Last updated at Posted at 2025-12-23

はじめに

Day23 で、

✅ 投稿作成(Create)
✅ React から投稿送信

ができるようになりました。

残っているのは…

「編集・削除」+「誰がそれをできるのか」

今日は CRUD 完成直前の重要回 です。

今日のゴール

・投稿編集 API(Update)を実装する

・投稿削除 API(Delete)を実装する

・投稿者本人のみ操作可能 にする

・権限制御の考え方を理解する

なぜ権限制御が必要?

もし制御が無いと…

・他人の投稿を編集できる

・他人の投稿を削除できる

・API として致命的 😇

👉 「認証」+「認可」 が揃って初めて安全です。

認証 vs 認可

種類 役割
認証 あなたは誰?
認可 それをやっていい?

今日は 認可 を実装します。

ルーティング定義

routes/api.php

Route::middleware('auth:api')->group(function () {
    Route::put('/posts/{post}', [PostController::class, 'update']);
    Route::delete('/posts/{post}', [PostController::class, 'destroy']);
});

投稿編集 API(Laravel)

public function update(Request $request, Post $post)
{
    // 権限制御
    if ($post->user_id !== auth('api')->id()) {
        return response()->json([
            'status' => 'error',
            'message' => '権限がありません'
        ], 403);
    }

    $request->validate([
        'title' => 'required|string|max:255',
        'body' => 'nullable|string',
    ]);

    $post->update($request->only('title', 'body'));

    return response()->json([
        'status' => 'success',
        'data' => $post
    ]);
}

投稿削除 API(Laravel)

public function destroy(Post $post)
{
    if ($post->user_id !== auth('api')->id()) {
        return response()->json([
            'status' => 'error',
            'message' => '権限がありません'
        ], 403);
    }

    $post->delete();

    return response()->json([
        'status' => 'success'
    ]);
}

なぜ 403 を返す?

403 Forbidden

・認証はされている

・だが権限が無い

👉 401 と使い分けるのが重要

React 側:編集・削除ボタン表示制御

{post.user_id === currentUser.id && (
  <>
    <button onClick={() => editPost(post)}>編集</button>
    <button onClick={() => deletePost(post.id)}>削除</button>
  </>
)}

React 側:削除処理

const deletePost = async (id) => {
  const token = localStorage.getItem('token');

  await fetch(`http://localhost/api/posts/${id}`, {
    method: 'DELETE',
    headers: {
      Authorization: `Bearer ${token}`
    }
  });

  setPosts(posts.filter(post => post.id !== id));
};

React 側:編集処理(簡易)

const updatePost = async (id, title, body) => {
  const token = localStorage.getItem('token');

  const res = await fetch(`http://localhost/api/posts/${id}`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`
    },
    body: JSON.stringify({ title, body })
  });

  const data = await res.json();
  // state 更新処理
};

サーバ側でも必ず制御する理由

❌ フロントだけ制御
→ API を直接叩けば突破可能

サーバ側で最終判断
→ セキュリティ担保

よくあるミス

❌ user_id をリクエストから受け取る

👉 なりすまし可能(NG)

❌ 401 と 403 の混同

・未ログイン → 401

・権限なし → 403

今日のポイント

・CRUD の U / D を実装

・認可は必須

・投稿者本人のみ操作可能

・サーバ側チェックが最重要

今日のまとめ

・投稿編集・削除 API を実装した

・権限制御を入れた

・API として安全になった

・CRUD がほぼ完成した 🎉

次回 Day25(最終日 🎄)

ついに最終回です。

Day25 — リクエストレスポンスから学んだAPI設計まとめ&今後の学習ロードマップ

「25日間の総まとめ」+次に何を学べばいいか
を整理します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?