👤 ユーザーサービス
User Serviceは、CRUD操作を備えたユーザーエンティティを管理するための完全なREST APIを提供します。Nodeblocksの関数型コンポジションアプローチを使用して構築され、MongoDBとシームレスに統合されます。
🚀 クイックスタート
import express from 'express';
import { middlewares, services, drivers } from '@nodeblocks/backend-sdk';
const { nodeBlocksErrorMiddleware } = middlewares;
const { userService } = services;
const { withMongo } = drivers;
const connectToDatabase = withMongo('mongodb://localhost:27017', 'dev', 'user', 'password');
express()
.use(
userService(
{
...(await connectToDatabase('users')),
...(await connectToDatabase('identities')),
...(await connectToDatabase('organizations')),
...(await connectToDatabase('products')),
},
{
authSecrets: {
authEncSecret: 'your-encryption-secret',
authSignSecret: 'your-signing-secret',
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001',
},
},
}
)
)
.use(nodeBlocksErrorMiddleware())
.listen(8089, () => console.log('Server running'));
📋 エンドポイント概要
| Method | Path | 説明 | 認証が必要 |
|---|---|---|---|
POST | /users | 新しいユーザーを作成 | ✅ Bearerトークン |
GET | /users/:profileId | IDでユーザーを取得 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
GET | /users | ユーザーをリスト/フィルタ | ✅ Bearerトークン(管理者のみ) |
GET | /profiles/identities/:identityId | アイデンティティIDでユーザープロフィールを取得 | ✅ Bearerトークン(自己アクセスのみ) |
PATCH | /users/:profileId | ユーザーを更新 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
DELETE | /users/:profileId | ユーザーを削除 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
ファイルアップロード操作
| Method | Path | 説明 | 認証が必要 |
|---|---|---|---|
GET | /user-profiles/:profileId/avatar-upload-url | ユーザーアバターをアップロードするための署名付きURLを取得 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
プロフィールフォロー操作
| Method | Path | 説明 | 認証が必要 |
|---|---|---|---|
PUT | /profiles/:profileId/profile-follows/:followProfileId | プロフィールフォロー関係を作成 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
DELETE | /profiles/:profileId/profile-follows/:followProfileId | プロフィールフォロー関係を削除 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
GET | /profiles/:profileId/followers | ページネーション付きでプロフィールフォロワーを取得 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
組織フォロー操作
| Method | Path | 説明 | 認証が必要 |
|---|---|---|---|
PUT | /profiles/:profileId/organization-follows/:followOrganizationId | 組織フォロー関係を作成 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
DELETE | /profiles/:profileId/organization-follows/:followOrganizationId | 組織フォロー関係を削除 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
商品いいね操作
| Method | Path | 説明 | 認証が必要 |
|---|---|---|---|
PUT | /profiles/:profileId/product-likes/:likeProductId | 商品いいね関係を作成 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
DELETE | /profiles/:profileId/product-likes/:likeProductId | 商品いいね関係を削除 | ✅ Bearerトークン(管理者またはプロフィール所有者) |
🗄️ エンティティスキーマ
ユーザーエンティティは、基本フィールド(自動生成)とユーザー固有のデータを組み合わせます:
{
"id": "string",
"createdAt": "string (datetime)",
"updatedAt": "string (datetime)",
"identityId": "string",
"name": "string",
"avatar": {
"url": "string",
"objectId": "string"
} | null,
"profileFollows": [
{
"followProfileId": "string"
}
],
"organizationFollows": [
{
"followOrganizationId": "string"
}
],
"productLikes": [
{
"likeProductId": "string"
}
]
}
フィールド詳細
| Field | Type | 自動生成 | 必須 | 説明 |
|---|---|---|---|---|
id | string | ✅ | ✅ | 一意の識別子(UUID) |
createdAt | datetime | ✅ | ✅ | 作成タイムスタンプ |
updatedAt | datetime | ✅ | ✅ | 最終更新タイムスタンプ |
identityId | string | ❌ | ✅ | リンクされたアイデンティティ識別子 |
name | string | ❌ | ✅ | ユーザーの表示名 |
avatar | object or null | ❌ | ❌ | ユーザーアバターメタデータまたはnull |
profileFollows | array | ✅ | ✅ | プロフィールフォロー関係の配列(空配列として初期化) |
organizationFollows | array | ✅ | ✅ | 組織フォロー関係の配列(空配列として初期化) |
productLikes | array | ✅ | ✅ | 商品いいね関係の配列(空配列として初期化) |
📝 注記: 自動生成フィールドはサービスによって設定され、作成/更新リクエストに含めるべきではありません。
🖼️ アバター:
avatarフィールドはnullまたはストレージメタデータを持つオブジェクトにすることができます。
🔐 認証ヘッダー
すべてのエンドポイントで、次のヘッダーを含めてください:
Authorization: Bearer <access_token>
x-nb-fingerprint: <device_fingerprint>
⚠️ 重要:
x-nb-fingerprintヘッダーは、認証時にフィンガープリントが指定された場合、すべての認証済みリクエストで必須です。これがない場合、リクエストは401 Unauthorizedを返します。
🔧 APIエンドポイント
1. ユーザーの作成
提供された情報で新しいユーザーを作成します。
リクエスト:
- Method:
POST - Path:
/users - Headers:
Content-Type: application/jsonAuthorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearerトークンが必要
リクエストボディ:
| Field | Type | 必須 | 説明 |
|---|---|---|---|
identityId | string | ✅ | リンクされたアイデンティティ識別子 |
name | string | ✅ | ユーザーの表示名 |
レスポンスボディ:
| Field | Type | 説明 |
|---|---|---|
id | string | 一意のユーザー識別子 |
identityId | string | リンクされたアイデンティティ識別子 |
name | string | ユーザーの表示名 |
avatar | object or null | ユーザーアバターメタデータまたはnull |
createdAt | string | 作成タイムスタンプ |
updatedAt | string | 最終更新タイムスタンプ |
バリデーション:
- スキーマバリデーション: 自動的に強制されます(identityIdとname必須;追加プロパティなし)
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールまたは対象アイデンティティの自己アクセスが必要
リクエスト例:
curl -X POST {{host}}/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9",
"name": "John Doe"
}'
成功レスポンス:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9",
"name": "John Doe",
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
}
エラーレスポンス:
リクエストボディに必須フィールドがない場合:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'identityId'",
"request body must have required property 'name'",
"request body must NOT have additional properties"
]
}
}
認証トークンが提供されていない場合:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": {
"message": "token could not be verified"
}
}
データベース挿入操作が挿入されたIDを返さなかった場合:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Failed to create user"
}
}
予期しないエラーが発生した場合(データベース接続の問題など):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to create user"
}
}
2. IDでユーザーを取得
一意のIDで特定のユーザーを取得します。
リクエスト:
- Method:
GET - Path:
/users/:profileId - Headers:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearerトークンが必要(管理者またはプロフィール所有者)
URLパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
profileId | string | ✅ | 一意のユーザープロフィール識別子 |
レスポンスボディ:
| Field | Type | 説明 |
|---|---|---|
id | string | 一意のユーザー識別子 |
identityId | string | リンクされたアイデンティティ識別子 |
name | string | ユーザーの表示名 |
avatar | object or null | ユーザーアバターメタデータまたはnull |
createdAt | string | 作成タイムスタンプ |
updatedAt | string | 最終更新タイムスタンプ |
バリデーション:
- スキーマバリデーション: パスパラメータバリデーション(profileId必須)
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールまたは対象プロフィールの所有者が必要
リクエスト例:
curl {{host}}/users/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Authorization: Bearer your-access-token-here"
成功レスポンス:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9",
"name": "John Doe",
"avatar": null,
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
}
エラーレスポンス:
認証トークンが提供されていない場合:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": {
"message": "token could not be verified"
}
}
ユーザーがこのリソースにアクセスする権限がない場合:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": {
"message": "Identity is not authorized to access this resource"
}
}
指定されたIDのユーザーが存在しない場合:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "User profile not found"
}
}
予期しないエラーが発生した場合(データベース接続の問題など):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to get user"
}
}
3. ユーザーのリスト取得
オプションのフィルタリングとページネーションでユーザーのリストを取得します。
リクエスト:
- Method:
GET - Path:
/users - Headers:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearerトークンが必要(管理者のみ)
クエリパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
identityId | string | ❌ | アイデンティティ識別子でユーザーをフィルタ |
name | string | ❌ | 表示名でユーザーをフィルタ |
page | number | ❌ | ページ番号(1-1000) |
limit | number | ❌ | ページあたりの項目数(1-50) |
レスポンスボディ:
| Field | Type | 説明 |
|---|---|---|
data | array | ユーザーオブジェクトの配列 |
metadata | object | レスポンスメタデータ |
metadata.pagination | object | ページネーション情報 |
data配列内の各ユーザーオブジェクトには以下が含まれます:
| Field | Type | 説明 |
|---|---|---|
id | string | 一意のユーザー識別子 |
identityId | string | リンクされたアイデンティティ識別子 |
name | string | ユーザーの表示名 |
avatar | object or null | ユーザーアバターメタデータまたはnull |
profileFollows | array | プロフィールフォロー関係の配列 |
organizationFollows | array | 組織フォロー関係の配列 |
productLikes | array | 商品いいね関係の配列 |
createdAt | string | 作成タイムスタンプ |
updatedAt | string | 最終更新タイムスタンプ |
バリデーション:
- スキーマバリデーション: name(文字列)、pageとlimit(最小/最大制約付き整数)のクエリパラメータバリデーション
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールが必要
リクエスト例:
すべてのユーザーをリスト:
curl {{host}}/users \
-H "Authorization: Bearer <access-token>"
アイデンティティIDでフィルタ:
curl "{{host}}/users?identityId=811ff0a3-a26f-447b-b68a-dd83ea4000b9" \
-H "Authorization: Bearer <access-token>"
名前でフィルタ:
curl "{{host}}/users?name=John" \
-H "Authorization: Bearer <access-token>"
フィルタを組み合わせる:
curl "{{host}}/users?name=John&page=1&limit=20" \
-H "Authorization: Bearer <access-token>"
成功レスポンス:
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": [
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9",
"name": "John Doe",
"avatar": null,
"profileFollows": [],
"organizationFollows": [],
"productLikes": [],
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
},
{
"id": "8fec096b-1bc7-5bfe-c827-3600e8fe2790",
"identityId": "922ff1b4-b37g-558c-c79b-ee94fb5001c0",
"name": "Jane Smith",
"avatar": {
"url": "https://storage.example.com/avatars/avatar123.png",
"type": "image/png"
},
"profileFollows": [],
"organizationFollows": [],
"productLikes": [],
"createdAt": "2024-05-29T10:15:33.441Z",
"updatedAt": "2024-05-29T10:15:33.441Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 20,
"total": 2,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
}
エラーレスポンス:
予期しないエラーが発生した場合(データベース接続の問題、無効なフィルタ構文など):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to find users"
}
}
4. ユーザーの更新
部分的なデータで既存のユーザーを更新します。
リクエスト:
- Method:
PATCH - Path:
/users/:profileId - Headers:
Content-Type: application/jsonAuthorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearerトークンが必要(管理者またはプロフィール所有者)
URLパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
profileId | string | ✅ | 一意のユーザープロフィール識別子 |
リクエストボディ(必須、すべてのフィールドはオプション):
| Field | Type | 必須 | 説明 |
|---|---|---|---|
avatar | object or null | ❌ | ユーザーアバターメタデータまたはnull |
name | string | ❌ | ユーザーの表示名 |
注記: リクエストボディ内のすべてのフィールドはオプションですが、リクエストボディ自体は必須で、空にすることはできません。空のボディを送信すると400エラーが返されます。
レスポンスボディ:
| Field | Type | 説明 |
|---|---|---|
id | string | 一意のユーザー識別子 |
identityId | string | リンクされたアイデンティティ識別子 |
name | string | 更新されたユーザーの表示名 |
avatar | object or null | 更新されたユーザーアバターメタデータまたはnull |
createdAt | string | 作成タイムスタンプ |
updatedAt | string | 最終更新タイムスタンプ |
バリデーション:
- スキーマバリデーション: 自動的に強制されます(nameとavatarのみ許可;追加プロパティなし)
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールまたは対象プロフィールの所有者が必要
リクエスト例:
curl -X PATCH {{host}}/users/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{"name": "John Doe Updated"}'
成功レスポンス:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9",
"name": "John Doe",
"avatar": null,
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T14:22:15.789Z"
}
エラーレスポンス:
リクエストボディが空または欠落している場合:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Request body is required"
}
}
指定されたIDのユーザーが存在しない場合:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "User profile not found"
}
}
更新操作がデータを変更しなかった場合(変更が検出されなかった):
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Failed to update user"
}
}
予期しないエラーが発生した場合(データベース接続の問題など):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to update user"
}
}
5. ユーザーの削除
システムからユーザーを永続的に削除します。
リクエスト:
- Method:
DELETE - Path:
/users/:profileId - Headers:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearerトークンが必要(管理者またはプロフィール所有者)
URLパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
profileId | string | ✅ | 一意のユーザープロフィール識別子 |
レスポンスボディ:
| Field | Type | 説明 |
|---|---|---|
| レスポンスボディなし | - | 削除エンドポイントは成功時にレスポンスボディを返しません |
バリデーション:
- スキーマバリデーション: なし(DELETEリクエスト)
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールまたは対象プロフィールの所有者が必要
リクエスト例:
curl -X DELETE {{host}}/users/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Authorization: Bearer <access-token>"
成功レスポンス:
HTTP/1.1 204 No Content
エラーレスポンス:
指定されたIDのユーザーが存在しない場合:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "User not found"
}
}
予期しないエラーが発生した場合(データベース接続の問題など):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to delete user"
}
}
6. アバターアップロードURLの取得
ユーザーアバター画像を安全にアップロードするための事前署名付きURLを生成します。オブジェクトIDと一時的な署名付きURLを返します。
リクエスト:
- Method:
GET - Path:
/user-profiles/:profileId/avatar-upload-url - Headers:
Authorization: Bearer <token> - Authorization: Bearerトークンが必要(管理者またはプロフィール所有者)
URLパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
profileId | string | ✅ | 対象ユーザープロフィールID |
クエリパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
contentType | string | ✅ | 画像MIMEタイプ(列挙型: image/jpeg, image/png, image/webp, image/gif, image/svg+xml, image/avif, image/bmp, image/x-icon, image/tiff, image/heif, image/heic) |
contentLength | number | ✅ | ファイルサイズ(バイト単位、最大10MB = 10,000,000) |
レスポンスボディ:
| Field | Type | 説明 |
|---|---|---|
objectId | string | アバター用に生成されたストレージオブジェクトID |
url | string | ファイルをアップロードするための事前署名付きURL |
バリデーション:
- スキーマバリデーション: 画像アップロードスキーマを使用(コンテンツタイプとサイズ制約)
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールまたは対象プロフィールの所有者が必要
リクエスト例:
curl "{{host}}/user-profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/avatar-upload-url?contentType=image/jpeg&contentLength=524288" \
-H "Authorization: Bearer <access-token>"
成功レスポンス:
{
"objectId": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"url": "https://storage.googleapis.com/bucket/avatars/...&X-Goog-Expires=900&X-Goog-Signature=..."
}
7. アイデンティティIDでプロフィールを検索
特定のアイデンティティIDに関連付けられたページネーション付きユーザープロフィールを取得します。自動アバターURL正規化と自己アクセス制御を備えています。
リクエスト:
- Method:
GET - Path:
/profiles/identities/:identityId - Headers:
Authorization: Bearer <token> - Authorization: Bearerトークンが必要(自己アクセスのみ - ユーザーは自分のプロフィールのみ閲覧可能)
URLパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
identityId | string | ✅ | プロフィールを取得する対象アイデンティティID |
クエリパラメータ:
| Parameter | Type | 必須 | Default | 説明 |
|---|---|---|---|---|
page | number | ❌ | 1 | ページネーションのページ番号(1-1000) |
limit | number | ❌ | 10 | ページあたりのプロフィール数(1-50) |
レスポンス(200 - 成功):
{
"data": [
{
"id": "profile-123",
"name": "John Doe",
"avatar": {
"url": "https://cdn.example.com/avatars/profile-123.jpg",
"type": "image/jpeg"
},
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
],
"metadata": {
"pagination": {
"hasNext": false,
"hasPrev": false,
"limit": 10,
"page": 1,
"total": 1,
"totalPages": 1
}
}
}
エラーレスポンス:
401 Unauthorized: 認証トークンが欠落しているか無効403 Forbidden: 別のアイデンティティのプロフィールにアクセスしようとしている(自己アクセス違反)500 Internal Server Error: データベースまたはアバター処理エラー
ユースケース:
- 認証済みアイデンティティのユーザープロフィールを取得するモバイルアプリ
- ユーザープロフィール情報を表示するWebアプリケーション
- 関連プロフィールを表示するプロフィール管理インターフェース
8. プロフィールフォローの作成
2つのユーザープロフィール間のソーシャルフォロー関係を作成し、ソーシャルネットワーキング機能のためにユーザーが互いをフォローできるようにします。
リクエスト:
- Method:
PUT - Path:
/profiles/:profileId/profile-follows/:followProfileId - Headers:
Authorization: Bearer <token> - Authorization: Bearerトークンが必要(管理者またはプロフィール所有者)
- Body: 空(リクエストボディは不要)
URLパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
profileId | string | ✅ | フォローを実行するプロフィールのID |
followProfileId | string | ✅ | フォローされるプロフィールのID |
レスポンスボディ: 空(204 No Content)
バリデーション:
- スキーマバリデーション: プロフィールIDのパスパラメータバリデーション
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールまたはソースプロフィールの所有者が必要
- 両方のプロフィールがデータベースに存在する必要がある
- ビジネスロジック: 同じプロフィールの重複フォローを防止
エラーレスポンス:
400 Bad Request: 無効なプロフィールIDまたは不正なリクエスト401 Unauthorized: 認証トークンが欠落しているか無効403 Forbidden: ユーザーに権限がない(管理者またはプロフィール所有者ではない)404 Not Found: 1つまたは両方のプロフィールが存在しない409 Conflict: プロフィールは既にフォローされている500 Internal Server Error: データベース操作が失敗した
リクエスト例:
curl -X PUT "{{host}}/profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/profile-follows/f8c9b2a1-3d4e-5f6g-7h8i-9j0k1l2m3n4o5p" \
-H "Authorization: Bearer <access-token>"
成功レスポンス:
HTTP/1.1 204 No Content
重複フォローレスポンス:
HTTP/1.1 409 Conflict
Content-Type: application/json
{
"status": 409,
"message": "Profile is already followed",
"code": "ProfileAlreadyFollowedBlockError"
}
ユースケース:
- ソーシャルネットワーキング機能
- フォローしたプロフィールに基づくコンテンツのパーソナライゼーション
- フォロワー/フォロー中ネットワークの構築
- コミュニティエンゲージメントの追跡
9. プロフィールフォローの削除
2つのユーザープロフィール間のソーシャルフォロー関係を削除します(アンフォロー)。ユーザーが他のプロフィールへの接続を削除できるようにします。
リクエスト:
- Method:
DELETE - Path:
/profiles/:profileId/profile-follows/:followProfileId - Headers:
Authorization: Bearer <token> - Authorization: Bearerトークンが必要(管理者またはプロフィール所有者)
- Body: 空(リクエストボディは不要)
URLパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
profileId | string | ✅ | アンフォローを実行するプロフィールのID |
followProfileId | string | ✅ | アンフォローされるプロフィールのID |
レスポンスボディ: 空(204 No Content)
バリデーション:
- スキーマバリデーション: プロフィールIDのパスパラメータバリデーション
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールまたはソースプロフィールの所有者が必要
- 両方のプロフィールがデータベースに存在する必要がある
- フォロー関係が存在する必要がある
- ビジネスロジック: フォロー関係が存在しない場合、適切なエラーを返す
エラーレスポンス:
400 Bad Request: 無効なプロフィールIDまたは不正なリクエスト401 Unauthorized: 認証トークンが欠落しているか無効403 Forbidden: ユーザーに権限がない(管理者またはプロフィール所有者ではない)404 Not Found: プロフィールまたはフォロー関係が存在しない500 Internal Server Error: データベース操作が失敗した
リクエスト例:
curl -X DELETE "{{host}}/profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/profile-follows/f8c9b2a1-3d4e-5f6g-7h8i-9j0k1l2m3n4o5p" \
-H "Authorization: Bearer <access-token>"
成功レスポンス:
HTTP/1.1 204 No Content
フォローが見つからないレスポンス:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"status": 404,
"message": "Profile follow not found",
"code": "ProfileFollowNotFoundBlockError"
}
ユースケース:
- ソーシャルネットワーキング機能 - ユーザーのアンフォロー
- 関係管理 - 接続の削除
- プライバシー制御 - ソーシャル接続の管理
- コミュニティエンゲージメントの追跡
10. プロフィールフォロワーの取得
特定のプロフィールのフォロワーのページネーション付きリストを取得します。正規化されたアバターURLを備えています。
リクエスト:
- Method:
GET - Path:
/profiles/:profileId/followers - Headers:
Authorization: Bearer <token> - Authorization: Bearerトークンが必要(管理者またはプロフィール所有者)
- Body: 空(リクエストボディは不要)
URLパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
profileId | string | ✅ | フォロワーを取得するプロフィールのID |
クエリパラメータ:
| Parameter | Type | 必須 | Default | 説明 |
|---|---|---|---|---|
page | number | ❌ | 1 | ページネーションのページ番号(1-1000) |
limit | number | ❌ | 20 | ページあたりの結果数(1-50) |
レスポンスボディ: ページネーション付きフォロワーリストとメタデータを含むJSON
レスポンス構造:
{
"data": [
{
"id": "string",
"name": "string",
"avatar": {
"url": "string",
"type": "string"
}
}
],
"metadata": {
"pagination": {
"page": number,
"limit": number,
"total": number,
"totalPages": number
}
}
}
バリデーション:
- スキーマバリデーション: プロフィールIDのパスパラメータバリデーション
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールまたはプロフィールの所有者が必要
- プロフィールがデータベースに存在する必要がある
- ビジネスロジック: アバターURL正規化付きのページネーション付きリストを返す
エラーレスポンス:
400 Bad Request: 無効なプロフィールIDまたは不正なリクエスト401 Unauthorized: 認証トークンが欠落しているか無効403 Forbidden: ユーザーに権限がない(管理者またはプロフィール所有者ではない)404 Not Found: プロフィールが存在しない500 Internal Server Error: データベース操作が失敗した
リクエスト例:
curl -X GET "{{host}}/profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/followers?page=1&limit=20" \
-H "Authorization: Bearer <access-token>"
成功レスポンス:
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": [
{
"id": "user-456",
"name": "John Doe",
"avatar": {
"url": "https://storage.example.com/avatars/avatar123.png",
"type": "image/png"
}
},
{
"id": "user-789",
"name": "Jane Smith",
"avatar": {
"url": "https://storage.example.com/avatars/avatar456.jpg",
"type": "image/jpeg"
}
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 20,
"total": 50,
"totalPages": 3
}
}
}
プロフィールが見つからないレスポンス:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"status": 404,
"message": "Profile not found",
"code": "ProfileNotFoundBlockError"
}
ユースケース:
- ソーシャルネットワーキング機能 - フォロワーリストの表示
- アナリティクス - フォロワー数の追跡と成長
- 関係管理 - ソーシャル接続の閲覧と管理
- コミュニティエンゲージメント - フォロワーベースのコンテンツ配信
主な機能:
- ページネーション: 大きなフォロワーリストの効率的な処理
- アバター正規化: ストレージ参照からアクセス可能なURLへの自動変換
- 柔軟なクエリ: カスタマイズ可能なページサイズとページ番号
- パフォーマンス: $elemMatch演算子を使用した最適化されたMongoDBクエリ
11. 組織フォローの作成
ユーザープロフィールと組織間のソーシャルフォロー関係を作成し、ユーザーが組織の更新を購読できるようにします。
リクエスト:
- Method:
PUT - Path:
/profiles/:profileId/organization-follows/:followOrganizationId - Headers:
Authorization: Bearer <token> - Authorization: Bearerトークンが必要(管理者またはプロフィール所有者)
- Body: 空(リクエストボディは不要)
URLパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
profileId | string | ✅ | フォローを実行するプロフィールのID |
followOrganizationId | string | ✅ | フォローされる組織のID |
レスポンスボディ: 空(204 No Content)
バリデーション:
- スキーマバリデーション: プロフィールと組織IDのパスパラメータバリデーション
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールまたはソースプロフィールの所有者が必要
- プロフィールと組織の両方がデータベースに存在する必要がある
- 組織が既にフォローされていない必要がある
- ビジネスロジック: 組織が既にフォローされている場合、適切なエラーを返す
エラーレスポンス:
400 Bad Request: 無効なプロフィール/組織IDまたは不正なリクエスト401 Unauthorized: 認証トークンが欠落しているか無効403 Forbidden: ユーザーに権限がない(管理者またはプロフィール所有者ではない)404 Not Found: プロフィールまたは組織が存在しない409 Conflict: 組織は既にフォローされている500 Internal Server Error: データベース操作が失敗した
リクエスト例:
curl -X PUT "{{host}}/profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/organization-follows/org-abc-123" \
-H "Authorization: Bearer <access-token>"
成功レスポンス:
HTTP/1.1 204 No Content
組織が既にフォローされているレスポンス:
HTTP/1.1 409 Conflict
Content-Type: application/json
{
"status": 409,
"message": "Organization is already followed",
"code": "OrganizationAlreadyFollowedBlockError"
}
プロフィール/組織が見つからないレスポンス:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"status": 404,
"message": "Profile not found",
"code": "ProfileNotFoundBlockError"
}
ユースケース:
- ソーシャルネットワーキング機能 - 組織のフォロー
- 関係管理 - 組織への接続の作成
- コンテンツ購読 - ユーザーが組織の更新を購読できるようにする
- コミュニティエンゲージメント - 組織ベースのコンテンツ配信
主な機能:
- 重複防止: プロフィールが同じ組織を複数回フォローすることを防止
- 認証: 認証済みユーザーのみがフォロー関係を作成できることを保証
- バリデーション: プロフィールと組織の存在の包括的なチェック
- パフォーマンス: フォロー作成のための効率的なMongoDB操作
12. 組織フォローの削除
ユーザープロフィールと組織間のソーシャルフォロー関係を削除し、ユーザーが組織の更新を購読解除できるようにします。
リクエスト:
- Method:
DELETE - Path:
/profiles/:profileId/organization-follows/:followOrganizationId - Headers:
Authorization: Bearer <token> - Authorization: Bearerトークンが必要(管理者またはプロフィール所有者)
- Body: 空(リクエストボディは不要)
URLパラメータ:
| Parameter | Type | 必須 | 説明 |
|---|---|---|---|
profileId | string | ✅ | フォローを削除するプロフィールのID |
followOrganizationId | string | ✅ | アンフォローされる組織のID |
レスポンスボディ: 空(204 No Content)
バリデーション:
- スキーマバリデーション: プロフィールと組織IDのパスパラメータバリデーション
- ルートバリデーター:
- 認証済みリクエストが必要(bearerトークン)
- 管理者ロールまたはソースプロフィールの所有者が必要
- プロフィールと組織の両方がデータベースに存在する必要がある
- 削除するには組織フォロー関係が存在する必要がある
- ビジネスロジック: フォロー関係が存在しない場合、404を返す(サイレント成功ではない)
エラーレスポンス:
400 Bad Request: 無効なプロフィール/組織IDまたは不正なリクエスト401 Unauthorized: 認証トークンが欠落しているか無効403 Forbidden: ユーザーに権限がない(管理者またはプロフィール所有者ではない)404 Not Found: プロフィール、組織、またはフォロー関係が存在しない500 Internal Server Error: データベース操作が失敗した
リクエスト例:
curl -X DELETE "{{host}}/profiles/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/organization-follows/org-abc-123" \
-H "Authorization: Bearer <access-token>"
成功レスポンス:
HTTP/1.1 204 No Content
組織フォローが見つからないレスポンス:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"status": 404,
"message": "Organization follow not found",
"code": "OrganizationFollowNotFoundBlockError"
}
プロフィール/組織が見つからないレスポンス:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"status": 404,
"message": "Profile not found",
"code": "ProfileNotFoundBlockError"
}
ユースケース:
- ソーシャルネットワーキング機能 - 組織のアンフォロー
- 関係管理 - 組織への接続の削除
- コンテンツ購読管理 - 組織の更新の購読解除
- コミュニティエンゲージメント - 動的な組織関係管理
主な機能:
- 存在バリデーション: フォロー関係が存在しない場合、404を返す(サイレント失敗を防止)
- 認証: 認証済みユーザーのみがフォロー関係を削除できることを保証
- バリデーション: プロフィール、組織、フォロー関係の存在の包括的なチェック
- パフォーマンス: 存在チェック付きの効率的なMongoDB $pull操作
13. 商品いいねの作成
ユーザープロフィールの商品いいね関係を作成します(商品をお気に入りに追加)。
リクエスト:
- Method:
PUT - Path:
/profiles/:profileId/product-likes/:likeProductId - Headers:
Authorization: Bearer <access_token>x-nb-fingerprint: <device_fingerprint>
- Path Parameters:
profileId(string, required): 商品にいいねするプロフィールのIDlikeProductId(string, required): いいねされる商品のID
- Body: 空(リクエストボディは不要)
レスポンス:
成功(201 Created):
(Empty body)
エラーレスポンス:
{
"error": {
"message": "Validation Error",
"data": [
"path parameter 'profileId' is required",
"path parameter 'likeProductId' is required"
]
},
"status": 400
}
{
"error": {
"message": "token could not be verified"
},
"status": 401
}
{
"error": {
"message": "Identity is not authorized to access this resource"
},
"status": 403
}
{
"error": {
"message": "Profile not found"
},
"status": 404,
"code": "ProfileNotFoundBlockError"
}
{
"error": {
"message": "Product not found"
},
"status": 404,
"code": "ProductNotFoundBlockError"
}
{
"error": {
"message": "Product is already liked"
},
"status": 409,
"code": "ProductAlreadyLikedBlockError"
}
{
"error": {
"message": "Failed to create product like"
},
"status": 500,
"code": "ProfileUnexpectedDBError"
}
ユースケース:
- 商品エンゲージメント機能 - 商品のいいねまたはお気に入り追加
- ウィッシュリスト管理 - お気に入りに商品を追加
- 商品レコメンデーション - ユーザーの好みの追跡
- Eコマース機能 - 商品インタラクションの追跡
主な機能:
- 重複防止: 商品が既にいいねされている場合、409を返す(重複エントリを防止)
- 認証: 認証済みユーザーのみが商品いいねを作成できることを保証
- バリデーション: プロフィールと商品の存在の包括的なチェック
- パフォーマンス: $ne演算子を使用した重複チェック付きの効率的なMongoDB $push操作
14. 商品いいねの削除
ユーザープロフィールから商品いいね関係を削除します(商品のお気に入り解除)。
リクエスト:
- Method:
DELETE - Path:
/profiles/:profileId/product-likes/:likeProductId - Headers:
Authorization: Bearer <access_token>x-nb-fingerprint: <device_fingerprint>
- Path Parameters:
profileId(string, required): 商品のいいねを解除するプロフィールのIDlikeProductId(string, required): いいねを解除される商品のID
- Body: 空(リクエストボディは不要)
レスポンス:
成功(204 No Content):
(Empty body)
エラーレスポンス:
{
"error": {
"message": "Validation Error",
"data": [
"path parameter 'profileId' is required",
"path parameter 'likeProductId' is required"
]
},
"status": 400
}
{
"error": {
"message": "token could not be verified"
},
"status": 401
}
{
"error": {
"message": "Identity is not authorized to access this resource"
},
"status": 403
}
{
"error": {
"message": "Profile not found"
},
"status": 404,
"code": "ProfileNotFoundBlockError"
}
{
"error": {
"message": "Product not found"
},
"status": 404,
"code": "ProductNotFoundBlockError"
}
{
"error": {
"message": "Product like not found"
},
"status": 404,
"code": "ProductLikeNotFoundBlockError"
}
{
"error": {
"message": "Failed to delete product like"
},
"status": 500,
"code": "ProfileUnexpectedDBError"
}
ユースケース:
- 商品エンゲージメント機能 - いいねの解除またはお気に入りからの削除
- ウィッシュリスト管理 - お気に入りから商品を削除
- 商品レコメンデーション - ユーザーの好みの更新
- Eコマース機能 - 商品インタラクションの管理
主な機能:
- 存在バリデーション: いいね関係が存在しない場合、404を返す(サイレント失敗を防止)
- 認証: 認証済みユーザーのみが商品いいねを削除できることを保証
- バリデーション: プロフィール、商品、いいね関係の存在の包括的なチェック
- パフォーマンス: 存在チェック付きの効率的なMongoDB $pull操作
⚙️ 設定オプション
サービス設定
interface UserServiceConfiguration {
authSecrets: {
authEncSecret: string; // JWT encryption secret
authSignSecret: string; // JWT signing secret
};
identity?: {
typeIds?: {
admin: string; // Admin user type identifier
guest: string; // Guest user type identifier
regular: string; // Regular user type identifier
};
};
}
設定詳細
ユーザーサービスの設定は、セキュリティとユーザータイプ管理のために論理的なグループに整理されています。
🔐 セキュリティ設定
authSecrets - JWTトークンセキュリティシークレット
- Type:
{ authEncSecret: string; authSignSecret: string } - 説明: JWT暗号化と署名のためのシークレットキー(トークン検証に使用)
- 必須: はい(本番環境用)
- 子プロパティ:
authEncSecret: JWTペイロード暗号化のためのシークレットキーauthSignSecret: JWT署名検証のためのシークレットキー
👥 ユーザータイプ設定
identity.typeIds - ユーザータイプ識別子設定
- Type:
{ admin?: string; guest?: string; regular?: string } - 説明: ロールベースアクセス制御のためのカスタムユーザータイプ識別子
- デフォルト:
undefined(デフォルトのタイプバリデーションを使用) - 子プロパティ:
admin: 管理者ユーザータイプ識別子- Type:
string - 説明: 管理者ユーザー用のカスタム識別子
- ユースケース: 管理操作のためのロールベースアクセス制御
- 例:
"admin","administrator","superuser"
- Type:
guest: ゲストユーザータイプ識別子- Type:
string - 説明: ゲストユーザー用のカスタム識別子
- ユースケース: 認証されていないまたは一時的なユーザー向けの限定アクセス
- 例:
"guest","visitor","anonymous"
- Type:
regular: 通常ユーザータイプ識別子- Type:
string - 説明: 通常ユーザー用のカスタム識別子
- ユースケース: 標準的なユーザーアクセス権限
- 例:
"user","member","customer"
- Type:
設定例
const userConfig = {
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET || 'your-enc-secret',
authSignSecret: process.env.AUTH_SIGN_SECRET || 'your-sign-secret'
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001'
}
}
};
🚨 エラーハンドリング
すべてのユーザーサービスエラーは、適切なHTTPステータスコードと共にJSON形式で返されます:
一般的なエラーコード
| Status | Error Message | 説明 |
|---|---|---|
| 400 | Validation Error | 無効なリクエストボディ形式または必須フィールドの欠落 |
| 400 | Failed to create user | データベース挿入操作が挿入されたIDを返さなかった |
| 400 | Failed to update user | 更新操作がデータを変更しなかった(変更が検出されなかった) |
| 401 | token could not be verified | 認証トークンが欠落しているか無効 |
| 403 | Identity is not authorized to access this resource | 権限が不足しています |
| 403 | User is not authorized to access this resource | ユーザーに必要な権限がありません(管理者アクセス) |
| 404 | User profile not found | GET/PATCH操作に対してユーザーが存在しません |
| 404 | User not found | DELETE操作に対してユーザーが存在しません |
| 500 | Failed to create user | 作成中のデータベース接続の問題または予期しない失敗 |
| 500 | Failed to get user | 取得中のデータベース接続の問題または予期しない失敗 |
| 500 | Failed to find users | リスト取得中のデータベース接続の問題、無効なフィルタ構文、または予期しない失敗 |
| 500 | Failed to update user | 更新中のデータベース接続の問題または予期しない失敗 |
| 500 | Failed to delete user | 削除中のデータベース接続の問題または予期しない失敗 |
エラーレスポンス形式
{
"error": {
"message": "エラーメッセージの説明",
"data": ["追加のエラー詳細"]
}
}
バリデーションエラーには追加の詳細が含まれます:
{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'identityId'",
"request body must have required property 'name'"
]
}
}
🔗 関連ドキュメント
- Error Handling - エラーパターンの理解
- Schema Component - データバリデーションの概念
- Custom Service Tutorial - 独自のサービスを構築