CursorでUser is unauthorizedとCan‘t verify the user is human. Please try again.になった
起こっていた問題
Cursorのプロンプトを入力して、送信をすると以下のエラーが出るようになりました。
User is unauthorized (Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
Cursorにログインし直そうと思ったら、ログインフォームで以下のエラーが出ました。
Can‘t verify the user is human. Please try again.
原因と解決
開発の都合で端末の「日付と時刻」を過去日時に設定していたため。
端末の日付と時刻を現在日時に戻したら直りました。
解決のために参照したページ
以下の書き込みがあり、そのおかげで解決しました。
I had the same issue on a new PC, but syncing the system time fixed it.
翻訳すると以下の通り
新しい PC でも同じ問題が発生しましたが、システム時間を同期すると解決しました。
Cursorでブログのシステムを作ってみる日記 その0001
はじめに
Cursorに慣れるために具体的に何か作ってみようと考え、markdownで記事を書けるブログのシステムを作ってみることにしました。
うまくいくかわかりませんが、自分のための日記です。
すごく長い記事です。
ChatGPTでどういう構成が良いか考える
ChatGPTに質問して、構成を考えました。
docker compose を使って、Next.js + API Routes + Prisma + Postgres という構成で、mdで記事を書けるブログシステムを構築することにしました。
Gitリポジトリの作成
next_js_md_blogリポジトリを作成してcloneしました。
Cursorで質問しながら仕様を考える
CursorでAIに相談したところ以下のような感じで提案されたので、これに沿って作ってみようと思う。
技術構成
- Next.js(API Routes含む)
- Prisma
- PostgreSQL
- Docker Composeによる環境構築
- 記事本文はMarkdownで管理
機能要件
- 記事(Post)はMarkdown本文・タイトル・作成者・作成日時などを持つ
- 記事には複数のタグ(Tag)を付与できる
- 記事とタグは多対多リレーション
- ユーザー(User)はメールアドレス・パスワード・名前・管理者フラグ(isAdmin)を持つ
- 管理者ユーザー(isAdmin=true)のみがユーザーの追加・編集ができる
- 一般ユーザーは自分のマイページで記事の投稿・編集ができる
- 初期管理者ユーザーはPrisma Studioやスクリプト等で手動作成
データベース設計(Prismaスキーマ)
- User(ユーザー)
- Post(記事)
- Tag(タグ)
- PostTag(記事とタグの中間テーブル)
環境構築手順(推奨フロー)
- Next.jsアプリの初期化
- docker-compose.yml・Dockerfileの作成
- Prismaセットアップ・スキーマ作成
- .envにDATABASE_URLを設定
- docker composeで起動
- Prismaマイグレーション
- 依存パッケージのインストール
- Markdown記事管理用
- 認証・パスワード管理用
- 型定義
- 初期管理者ユーザーの作成
- 各種API・フロントエンド実装(次回以降の記事で)
- 認証機能の実装
- 記事投稿・編集機能
- タグ付け機能
- APIルートやフロントエンドの開発
Next.jsアプリの初期化
next_js_md_blogディレクトリで、以下のコマンドを実行しました。
npx create-next-app@latest .
リポジトリ作成時に README.md を作成していたため、失敗しました。
とりあえず README.md を削除して再実行しました。
対話形式の選択は以下の通り選択しました。
user@mac next_js_md_blog % npx create-next-app@latest . ✔ Would you like to use TypeScript? … Yes ✔ Would you like to use ESLint? … Yes ✔ Would you like to use Tailwind CSS? … No ✔ Would you like your code inside a `src/` directory? … No ✔ Would you like to use App Router? (recommended) … Yes ✔ Would you like to use Turbopack for `next dev`? … Yes ✔ Would you like to customize the import alias (`@/*` by default)? … No
今回生成されたpackage.jsonの記述内容は以下の通りでした。
{
"name": "next_js_md_blog",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0",
"next": "15.3.4"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "15.3.4",
"@eslint/eslintrc": "^3"
}
}
package.json に "type": "module", を追記する
"type": "module", を追記して以下のようにしました。
{
"name": "next_js_md_blog",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0",
"next": "15.3.4"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "15.3.4",
"@eslint/eslintrc": "^3"
}
}
セキュリティの観点から .gitignore に追加した方が良い項目があるか聞いてみる
CursorでAIに以下の質問をしてみました。
.gitignore ファイルの記述内容は適切? セキュリティの観点から追加して置いた方が良いファイルやディレクトリはある?
Prisma や Docker を使う前提というのもあり、いくつか項目を追加した方が良いということだったので、Agentモードで .gitignore を編集してもらった。
目視確認をしつつ、手で調整した。
Next.jsアプリの初期ファイルをコミットする
.gitignoreファイルが編集できたので一旦コミットしました。
どこでコミットとか今後は書きませんが、差分を確認しながら理解しやすい単位でコミットして進めていきます。
Next.jsアプリの開発サーバーを起動してみる
以下のコマンドを実行しました。
npm install
以下のコマンドを実行しました。
npm run dev
http://localhost:3000 で開発環境が起動できることが確認できました。
とりあえず control + c で止めておきます。
これで手順1が終わりました。
docker-compose.yml・Dockerfileの作成
手順2に進みます。
CursorのAgentモードでAIに作ってもらいました。
あくまでも開発環境用です。
本番環境用のdocker-compose.ymlはこのような記述内容では良くないのでセキュリティ観点で配慮が必要です。
本番環境ではハードコーディングをしないとか、どのような設定、どのような管理手法が良いのか、改めてAIに聞こうと思います。
docker-compose.ymlの記述内容は以下の通りです。
version: '3.8'
services:
db:
image: postgres:15
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: blog
ports:
- "5432:5432"
volumes:
- db_data:/var/lib/postgresql/data
app:
build: .
command: sh -c "npm install && npx prisma migrate deploy && npm run dev"
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://postgres:postgres@db:5432/blog
volumes:
- .:/app
- /app/node_modules
depends_on:
- db
volumes:
db_data:
Dockerfileの記述内容は以下の通りです。
FROM node:18 WORKDIR /app COPY package*.json ./ RUN npm install COPY . . EXPOSE 3000 CMD ["npm", "run", "dev"]
本番環境ではどうするのかAIに聞いてみる
要約すると以下のような返答だった。
- 機密情報は環境変数や.envで管理し、Gitに含めない
- DBポートは外部公開しない
- .dockerignoreで不要なファイルを除外
- 本番用のcomposeファイルを分ける
これで手順2が終わりました。
Prismaセットアップ・スキーマ作成
Prismaのインストール
next_js_md_blogディレクトリで、以下のコマンドを実行しました。
npm install prisma @prisma/client
Prismaの初期化
以下のコマンドを実行しました。
npx prisma init
以下のように表示されました。
user@mac next_js_md_blog % npx prisma init Fetching latest updates for this subcommand... ✔ Your Prisma schema was created at prisma/schema.prisma You can now open it in your favorite editor. warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information. Next steps: 1. Run prisma dev to start a local Prisma Postgres server. 2. Define models in the schema.prisma file. 3. Run prisma migrate dev to migrate your local Prisma Postgres database. 4. Tip: Explore how you can extend the ORM with scalable connection pooling, global caching, and a managed serverless Postgres database. Read: https://pris.ly/cli/beyond-orm More information in our documentation: https://pris.ly/d/getting-started
prisma/schema.prisma にスキーマを記述
CursorのAgentモードでAIに編集してもらいました。
以下の記述になりました。(後でわかることですが generator client ブロックの output の行は不要でした。)
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client-js"
output = "../app/generated/prisma"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
password String
name String?
isAdmin Boolean @default(false)
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id Int @id @default(autoincrement())
title String
content String // Markdown本文
author User @relation(fields: [authorId], references: [id])
authorId Int
tags PostTag[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Tag {
id Int @id @default(autoincrement())
name String @unique
posts PostTag[]
}
model PostTag {
post Post @relation(fields: [postId], references: [id])
postId Int
tag Tag @relation(fields: [tagId], references: [id])
tagId Int
@@id([postId, tagId]) // 複合主キー
}
.envにDATABASE_URLを設定
.envファイルを編集して、環境変数 DATABASE_URL を定義しました。
記述内容は以下の通りです。
DATABASE_URL="postgres://postgres:postgres@localhost:5432/blog"
AIによると、本番環境では .env で管理するより、以下の方法が適切なようです。
注意:このブログ記事で紹介している設定やコードは、あくまで開発環境構築用のサンプルです。
データベースのユーザー名やパスワード、DATABASE_URL などはチュートリアルやローカル開発用の一般的な初期値を使用しています。
本番環境で運用する際は、必ず強固なパスワードや適切な設定に変更し、機密情報はクラウドシークレット管理サービスなどで安全に管理してください。
また、APIキーや本番用の接続情報など、機密性の高い情報は絶対に公開しないようご注意ください。
代表的なクラウドシークレット管理サービスは以下の通りです。
これらのサービスは、アクセス権限や監査ログの管理もでき、インフラやCI/CDとの連携も容易です。
Prismaマイグレーションの実行
まずマイグレーションの前にDBの起動が必要です。
以下のコマンドを実行しました。
docker compose build
以下のコマンドを実行しました。
docker compose up -d
マイグレーションします。
以下のコマンドを実行しました。
npx prisma migrate dev --name init
Prisma StudioでDBをGUI確認
以下のコマンドを実行します。
npx prisma studio
自動的にブラウザが起動して http://localhost:5555/ が開き、データベースの各テーブルが確認できます。
終了する
ターミナルで control + c を押すとPrisma Studioを終了できます。
docker compose down で docker compose のサービスを終了できますが、データベースはまだ使うのでここではまだ終了しないでください。
これで手順6が終わりました。
依存パッケージのインストール
今決まっている仕様を実現していくうえで必要なパッケージを予めインストールします。
Markdown記事管理用
以下のコマンドを実行しました。
npm install gray-matter remark remark-html
認証・パスワード管理用
以下のコマンドを実行しました。
npm install next-auth bcrypt
環境変数管理用
以下のコマンドを実行しました。
npm install dotenv
型定義
以下のコマンドを実行しました。
npm install -D @types/bcrypt
これで手順7が終わりました。
初期管理者ユーザーの作成
初期管理者ユーザー作成用の環境変数を定義する
ログインしてブログの記事を書くことになるので、ユーザーを作成するscriptを作成します。
まず .env に初期管理ユーザー作成用の以下の環境変数を手で追加します。
ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=initial_password ADMIN_NAME=管理者
初期管理者ユーザー作成スクリプトを定義する
CursorのAgentモードで以下の内容で scripts/create-admin.js をAIに作ってもらいました。
import { PrismaClient } from '@prisma/client';
import bcrypt from 'bcrypt';
import dotenv from 'dotenv';
dotenv.config();
const prisma = new PrismaClient();
async function main() {
const adminEmail = process.env.ADMIN_EMAIL || 'admin@example.com';
const adminPassword = process.env.ADMIN_PASSWORD || 'admin';
const adminName = process.env.ADMIN_NAME || '管理者';
const password = await bcrypt.hash(adminPassword, 10);
await prisma.user.create({
data: {
email: adminEmail,
password,
name: adminName,
isAdmin: true,
}
});
console.log('管理者ユーザーを作成しました');
}
main()
.catch(e => {
console.error(e);
process.exit(1);
})
.finally(() => prisma.$disconnect());
スクリプトを実行してみるもエラーになる
node scripts/create-admin.js
エラーは詳細に書きませんが、エラーをAIのチャットに丸ごとペーストしたら、トラブルシューティングの方法を提案してくれました。
Prisma Clientのコード生成をする
トラブルシューティングのひとつとして、以下のコマンドを実行しました。
npx prisma generate
以下の通り出力されました。
Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma ✔ Generated Prisma Client (v6.10.1) to ./app/generated/prisma in 87ms Start by importing your Prisma Client (See: https://pris.ly/d/importing-client) Tip: Interested in query caching in just a few lines of code? Try Accelerate today! https://pris.ly/tip-3-accelerate
これをAIのチャットに貼ったら ./app/generated/prisma にアウトプットされてるのがおかしい。とのこと。
prisma/schema.prisma のアウトプットパスを修正する
以下のようになっている箇所を
generator client {
provider = "prisma-client-js"
output = "../app/generated/prisma"
}
以下の通り変更しました。
generator client {
provider = "prisma-client-js"
}
Prisma Clientのコード生成をやり直す
もう一度以下のコマンドを実行しました。
npx prisma generate
以下の通り出力され、デフォルトの出力先である ./node_modules/@prisma/client に生成されました。
Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma ✔ Generated Prisma Client (v6.10.1) to ./node_modules/@prisma/client in 46ms Start by importing your Prisma Client (See: https://pris.ly/d/importing-client) Tip: Want to turn off tips and other hints? https://pris.ly/tip-4-nohints
私は Prisma を初めて使っているのですが、初めて使うツールをAIに言われるまま適当に設定しているとこのようなトラブルに見舞われる。
ただ、それはそれとして、問題が起こったときのトラブルシューティングも早かった。
スクリプトを実行し直す
以下のコマンドを実行しました。
node scripts/create-admin.js
以下の通り出力されました。
管理者ユーザーを作成しました
GUIでデータを確認する
以下のコマンドを再度実行して、ブラウザからユーザーテーブルのレコードを確認します。
npx prisma studio
ユーザーテーブルにレコードが追加されたことが確認できました。
control + c で、prisma studioを終了します。
ユーザー作成のために .env に定義した環境変数についての注意事項
AIによると以下の注意事項があります。
本番環境を構築・運用していく際は、データベースのパスワードや初期管理者ユーザーのパスワード、APIキーなどの機密情報を安全に管理することが非常に重要です。
.envファイルに機密情報を記載する方法は開発環境では便利ですが、本番環境では漏洩リスクや管理ミスの危険性があるため、よりセキュアな方法を選ぶことをおすすめします。
本番運用では、クラウドシークレット管理サービスを利用するのが最も安全で堅牢な方法です。
これらのサービスを使うことで、機密情報を暗号化して安全に保管し、必要なときだけアプリやスクリプトが安全に取得できます。代表的なサービスは以下の通りです。
これらのサービスは、アクセス権限や監査ログの管理もでき、インフラやCI/CDとの連携も容易です。
まとめ
各種API・フロントエンド実装
ようやくAIから「環境構築手順(推奨フロー)」として提案された「手順9. 各種API・フロントエンド実装」まできました。
とても長くなりそうなのと、ますますごちゃごちゃしそうなので、続きは次回以降の記事で以下のようなことを順次やっていこうと思います。
まずは「認証機能の実装」ですね。
それにしてもAIに自然言語で日本語で質問して日本語で答えてもらうのは、自分でWeb検索して英語のドキュメントを翻訳しながら環境構築するより何倍も早い。
AIコーディングなどについて学習し始める
はじめに
適当に記事を読んではここに追加していこうかと思う。
最近の所感
- Cursorで主にReactのコードを編集しているが、ファイル分割のような「手順によっては簡単に安全にできるタスク」については、手順を人間が考えたうえで、タスクを分割して順番にAIに与えると精度が上がる。雑に指示を出して上手くいく場合もあるが、その場合は制度は低い。
- 「適切な単位でファイル分割してください。」とかだと、フック関数1つにつき1ファイルに分割してしまうことが多かったり、React.MutableRefObject型の変数を考慮してくれなかった。これも人間がある程度それを考慮して、何をどう切り出すかを明確に指示すれば、まあ上手くいき始めた。自分の手でやるよりはプロンプトを適切に書く方が早い。ルールを設定すれば、雑なプロンプトでも適切にやってくれるのかもしれない。
読んだ記事
総合的な記事
Cursor
Amazon Bedrock
- ファンデーションモデルを使用してジェネレーティブな AI アプリケーションを構築 — Amazon Bedrock — AWS
- 【初心者向け】AWSで生成AIを試してみよう Amazon Bedrockではじめる生成AI|伊藤忠テクノソリューションズ
リモートGitHub MCPサーバー
CursorでAIにコードレビューしてもらう
ChatGPTによると、以下のプロンプトでできるらしいけど試していない。
@git diff abc1234..def5678 この変更内容をレビューしてください。改善点や問題点があれば教えてください。
Playwrightのテストでブラウザのコンソールに表示されるメッセージをターミナルに表示する
はじめに
CIなどでheadlessでテストを実行している場合に、ブラウザのコンソールに表示されるメッセージを確認する方法です。
サンプルコード
以下のように 'console' イベントをリスニングします。
import { test, expect } from '@playwright/test';
test('コンソールログをキャプチャする', async ({ page }) => {
// console イベントのリスニングを開始
page.on('console', (msg) => {
// コンソールメッセージをターミナルに表示
console.log(`msg.type(): ${msg.type()}`);
console.log(`msg.text(): ${msg.text()}`);
console.log(`msg.args(): ${msg.args()}`);
console.log(`msg.location(): ${msg.location()}`);
});
// テスト実行
await page.goto('http://localhost:3000');
await expect(page).toHaveTitle('Example');
});
PlaywrightのMock APIsでGETやPOSTなどのメソッド毎にレスポンスを分ける
参照したページ
サンプルコード
以下のように route.request().method() を呼び出すとメソッドが取得できます。
// Handle GET requests.
await page.route('**/*', async route => {
if (route.request().method() !== 'GET') {
await route.fallback();
return;
}
// Handling GET only.
// ...
});
// Handle POST requests.
await page.route('**/*', async route => {
if (route.request().method() !== 'POST') {
await route.fallback();
return;
}
// Handling POST only.
// ...
});
Playwrightで$や*が含まれるspecファイルのテストをする
はじめに
以下のような $ が含まれるpathのテストを実行しようとしたらエラーになりました。
tests/example.$id.spec.ts
表示されたエラー
以下のエラーメッセージが表示されました。
Error: No tests found. Make sure that arguments are regular expressions matching test files. You may need to escape symbols like "$" or "*" and quote the arguments.
翻訳すると以下の通りでした。
エラー: テストが見つかりません。 引数がテスト ファイルに一致する正規表現であることを確認してください。 「$」や「*」などの記号をエスケープし、引数を引用符で囲む必要がある場合があります。
実行する
エラーメッセージを読んだままですが、以下のように$をエスケープしたうえで、引用符で囲います。
yarn playwright test './tests/example.\$id.spec.ts'