---
title: コンテンツにコメント機能を追加する
description: Kurocoを利用したプロジェクトで、アクティビティ:コメント機能の実装方法を紹介します。本チュートリアルではフロントエンドのコードとして、Nuxt.jsを紹介します。 
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Kurocoを利用したプロジェクトで、アクティビティ:コメント機能の実装方法を紹介します。  
本チュートリアルではフロントエンドのコードとして、Nuxt.jsを紹介します。  

:::info
本チュートリアルでは以下のバージョンでコードを書いています。  
Nuxt2: v2.15.8  
Nuxt3: v3.8.0  
:::

## 事前準備
### Nuxt.jsプロジェクトの作成について
このページは、KurocoとNuxt.jsでのプロジェクトが構築済み、
かつ既に何らかの記事が閲覧できること、また`profile`エンドポイントが有効であることを前提としています。  
まだNuxt.jsプロジェクトを構築していない場合、[チュートリアル ->KurocoとNuxt.jsで、コンテンツ一覧ページを作成する](/ja/docs/tutorials/integrate-kuroco-with-nuxt/)を参照してください。  
また`profile`などは[チュートリアル ->KurocoとNuxt.jsで、ログイン画面を構築する](/ja/docs/tutorials/integrate-login/)を参考にしてください。
今回はcookieによるログイン制御を前提とします。

作成済みの「お知らせ詳細」のエンドポイントをコピー、未ログインメンバーによるコメントの許可設定をした後、お知らせ詳細とそれに紐づくコメントのフォームを作成します。

### APIの作成
未承認ユーザーからの操作を許可するために、新しくAPIを作成します。  
Kuroco管理画面のAPIより「追加」をクリックします。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/16730cd0c84c75934d48196e0265c5d6.png)
API作成画面が表示されます。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/9757238971ca5ead28886be1d43bf9c6.png)

下記入力し「追加する」をクリックします。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/a1a5446771ba224317a050f552e1a6ac.png)

|項目|設定内容|
| :--- | :--- |
|タイトル|Comment Test|
|版|1.0|
|説明|コメント機能の確認用API|

### CORSの設定
次にCORSの設定をします。[CORSを設定する] をクリックします。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/4a433b3a87d117c8a46a3a97cab2f73b.png)
CORS_ALLOW_ORIGINSの [Add Origin] をクリックし、下記を追加します。  
- http://localhost:3000

CORS_ALLOW_METHODSの [Add Method] をクリックし、下記を追加します。  
- GET
- POST
- OPTIONS

設定できたら[保存する]をクリックし、CORSの設定が完了です。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/bc12583c6133922cf88275baf0a7b857.png)
## ログイン不要でコメント機能の動作を確認する
### アクティビティ定義の作成
未承認ユーザーからのコメント操作を許可するために、アクティビティ定義を編集します。  
[アクティビティ定義]をクリックします。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/b73cbe0b67685431b15982c5100fcba2.png)
[追加する]をクリックします。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/9454d944dbb2affe08d47744bb752918.png)
APIリクエスト制限、投稿制限を`閲覧可`、`即公開`として[追加する]をクリックします。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/12671f9adb9bc5b7cf15e2206d0ae29f.png)
後ほど利用するので、作成したアクティビティIDをメモしておきます。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/cc89e2ddd79925992af7178285aab6fe.png)
### エンドポイントの作成
エンドポイントを作成します。今回は下記エンドポイントを作成します。

- newsdetailエンドポイント -> ニュース詳細
- commentsエンドポイント -> コメントの取得用
- commentエンドポイント -> コメントの追加用
- comment_deleteエンドポイント -> コメントの削除用

Comment TestのAPIで「新しいエンドポイントの追加」をクリックし、それぞれ作成します。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/1dfbc16f42969870fe73e2a3ff327888.png)
#### newsdetailエンドポイントの作成
newsdetailエンドポイントを下記設定にて作成します。  

![Image from Gyazo](https://t.gyazo.com/teams/diverta/5ec0d55eca055cea3aa8c25b3f0720aa.png)

|項目|設定内容|
| :--- | :--- |
|パス|newsdetail|
|カテゴリー|コンテンツ|
|モデル|Topics v1|
|オペレーション|details|
|APIリクエスト制限|**None**|
|topics_group_id|表示するコンテンツ定義ID(9)|

設定完了後、「追加する」をクリックしnewsdetailエンドポイント完成です。  

#### commentsエンドポイントの作成
commentsエンドポイントを下記設定にて作成します。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/6a510d7e58e103626381eef6ac64acf3.jpg)

|項目|設定内容|
| :--- | :--- |
|パス|comments|
|カテゴリー|アクティビティ|
|モデル|Comment v1|
|オペレーション|list|
|APIリクエスト制限|**None**|
|id|アクティビティID(37)|
|module_type|topics|
|new_order_flg|チェックを入れる|

設定完了後、「追加する」をクリックしcommentsエンドポイント完成です。  

#### commentエンドポイントの作成
commentエンドポイントを下記設定にて作成します。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/7c65e689f7f95634c9ecf368f5487b09.png)

|項目|設定内容|
| :--- | :--- |
|パス|comment|
|カテゴリー|アクティビティ|
|モデル|Comment v1|
|オペレーション|insert|
|APIリクエスト制限|**None**|
|id|アクティビティID(37)|

設定完了後、「追加する」をクリックしcommentエンドポイント完成です。

#### comment_deleteエンドポイントの作成
comment_deleteエンドポイントを下記設定にて作成します。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/2dce8c50c45270be614df57cca00918f.png)

|項目|設定内容|
| :--- | :--- |
|パス|comment_delete|
|カテゴリー|アクティビティ|
|モデル|Comment v1|
|オペレーション|delete|
|APIリクエスト制限|**None**|
|id|アクティビティID(37)|

設定完了後、「追加する」をクリックしcomment_deleteエンドポイント完成です。  

:::caution
今回の例では、コメントの追加/削除するエンドポイントはセキュリティ`None`にしていますが、実際のサイトではコメントの追加/削除を許可するグループを設定してください。 
::: 

### フロントエンドの設定
#### コメント機能付きニュース詳細ページの追加
今回は既存のニュース詳細画面を参考に画面を作成し、同ページにコメント機能を追加します。  
まずは未承認のユーザーでもコメントの閲覧/投稿がきるようにし動作の確認をします。  

画面を表示する際にニュースへ紐づく全てのコメントを取得し、表示します。  

ユーザー名入力欄とコメント投稿のフォームが存在し、ユーザー名入力のあと、追加したコメントは即時に画面へ反映されます。  
またコメントそれぞれには削除ボタンが存在します。  

:::tip
コメントの削除はコメントの投稿・削除にパスワード(delkey)を使用するように構築するか、ログインを前提として、コメントを投稿した本人でないとできません。  
この段階では削除ボタンをクリックした場合、Code 422 "パスワードが一致しないか、書き込んだ本人でないため削除できません。" のエラーが発生します。  
:::

`/pages/news/test_with_comment.vue`を追加します。

<Tabs>
<TabItem value="Nuxt2" label="Nuxt2" default>

```markup reference title="/pages/news/test_with_comment.vue"
https://github.com/diverta/kuroco-documents/blob/main/sample_code/front-end/nuxtjs/test_with_comment_nodelete.vue
```

</TabItem>
<TabItem value="Nuxt3" label="Nuxt3" default>

```markup reference title="/pages/news/test_with_comment.vue"
https://github.com/diverta/kuroco-documents/blob/main/sample_code/front-end/nuxt3/test_with_comment_nodelete.vue
```

</TabItem>
</Tabs>

以下のようにコメントの追加ができることを確認します。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/50dc769924d1c6970ec7e06d1dab280d.gif)
### コメントを削除可能にする(delkeyの使用)

未承認のユーザーでもコメントの削除ができるようにするため、`delkey`を使用して削除をリクエストするように変更します。

`delkey`はコメントを追加する際に付与できる任意の値です。  
今回は以下の仕様で実装します。  
- コメントを追加する段階で`delkey`を自動的に付与
- `delkey`はブラウザのローカルストレージに保存
- 削除時にブラウザのローカルストレージから`delkey`を呼び出す
 
ブラウザへの保存はローカルストレージを使用するため、ブラウザの変更や異なる端末で操作再開する場合には削除できない点にご注意ください。

`/pages/news/test_with_comment.vue`を下記のように変更します。

<Tabs>
<TabItem value="Nuxt2" label="Nuxt2" default>

```markup reference title="/pages/news/test_with_comment.vue"
https://github.com/diverta/kuroco-documents/blob/main/sample_code/front-end/nuxtjs/test_with_comment_delkey.vue
```

</TabItem>
<TabItem value="Nuxt3" label="Nuxt3" default>

```markup reference title="/pages/news/test_with_comment.vue"
https://github.com/diverta/kuroco-documents/blob/main/sample_code/front-end/nuxt3/test_with_comment_delkey.vue
```

</TabItem>
</Tabs>

以下のようにコメント済みのもののみ削除ボタンが表示して削除ができることを確認します。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/89bd9515db9ebee883f82820d798c769.gif)

## コメントをログイン必須にする
コメント機能のような変更/削除のためのPOSTエンドポイントを無施策に開放してしまうと、DoS攻撃(同時に大量のデータをPOSTすることで、DBをパンクさせるサイバー攻撃)に弱くなります。  
Kurocoのエンドポイントでは、同じIPアドレスから短時間に何回もコメントをされた場合に、投稿を受け付けないエラーを返す機能を持っていますが、本チュートリアルではページの閲覧、コメントの表示・投稿・削除にログインを必須とさせるように実装します。  

### アクティビティ定義の更新
[アクティビティ定義]をクリックします。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/b73cbe0b67685431b15982c5100fcba2.png)
作成したアクティビティのタイトルをクリックします。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/4da9b7e7f6f85c4482c9994c1099fb19.png)
未ログインメンバーのAPIリクエスト制限、投稿制限を`閲覧不可`、`受け付けない`として[更新する]をクリックします。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/e8d8b0de0829984fa80f59410ad0e389.png)
### フロントエンドの更新

`/pages/news/test_with_comment.vue`を次のように修正します。

<Tabs>
<TabItem value="Nuxt2" label="Nuxt2" default>

```markup reference title="/pages/news/test_with_comment.vue"
https://github.com/diverta/kuroco-documents/blob/main/sample_code/front-end/nuxtjs/test_with_comment_login.vue
```

</TabItem>
<TabItem value="Nuxt3" label="Nuxt3" default>

```markup reference title="/pages/news/test_with_comment.vue"
https://github.com/diverta/kuroco-documents/blob/main/sample_code/front-end/nuxt3/test_with_comment_login.vue
```

</TabItem>
</Tabs>

最後に動作確認をして完了です。  
![Image from Gyazo](https://t.gyazo.com/teams/diverta/53497dec5cb300d45f6d187b6fdbb0d8.gif)