メインコンテンツまでスキップ
バージョン: 0.9.0 (最新)

👤 ユーザーサービス

Testing Status

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'));

📋 エンドポイント概要

MethodPath説明認証が必要
POST/users新しいユーザーを作成✅ Bearerトークン
GET/users/:profileIdIDでユーザーを取得✅ Bearerトークン(管理者またはプロフィール所有者)
GET/usersユーザーをリスト/フィルタ✅ Bearerトークン(管理者のみ)
GET/profiles/identities/:identityIdアイデンティティIDでユーザープロフィールを取得✅ Bearerトークン(自己アクセスのみ)
PATCH/users/:profileIdユーザーを更新✅ Bearerトークン(管理者またはプロフィール所有者)
DELETE/users/:profileIdユーザーを削除✅ Bearerトークン(管理者またはプロフィール所有者)

ファイルアップロード操作

MethodPath説明認証が必要
GET/user-profiles/:profileId/avatar-upload-urlユーザーアバターをアップロードするための署名付きURLを取得✅ Bearerトークン(管理者またはプロフィール所有者)

プロフィールフォロー操作

MethodPath説明認証が必要
PUT/profiles/:profileId/profile-follows/:followProfileIdプロフィールフォロー関係を作成✅ Bearerトークン(管理者またはプロフィール所有者)
DELETE/profiles/:profileId/profile-follows/:followProfileIdプロフィールフォロー関係を削除✅ Bearerトークン(管理者またはプロフィール所有者)
GET/profiles/:profileId/followersページネーション付きでプロフィールフォロワーを取得✅ Bearerトークン(管理者またはプロフィール所有者)

組織フォロー操作

MethodPath説明認証が必要
PUT/profiles/:profileId/organization-follows/:followOrganizationId組織フォロー関係を作成✅ Bearerトークン(管理者またはプロフィール所有者)
DELETE/profiles/:profileId/organization-follows/:followOrganizationId組織フォロー関係を削除✅ Bearerトークン(管理者またはプロフィール所有者)

商品いいね操作

MethodPath説明認証が必要
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"
}
]
}

フィールド詳細

FieldType自動生成必須説明
idstring一意の識別子(UUID)
createdAtdatetime作成タイムスタンプ
updatedAtdatetime最終更新タイムスタンプ
identityIdstringリンクされたアイデンティティ識別子
namestringユーザーの表示名
avatarobject or nullユーザーアバターメタデータまたはnull
profileFollowsarrayプロフィールフォロー関係の配列(空配列として初期化)
organizationFollowsarray組織フォロー関係の配列(空配列として初期化)
productLikesarray商品いいね関係の配列(空配列として初期化)

📝 注記: 自動生成フィールドはサービスによって設定され、作成/更新リクエストに含めるべきではありません。

🖼️ アバター: 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/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearerトークンが必要

リクエストボディ:

FieldType必須説明
identityIdstringリンクされたアイデンティティ識別子
namestringユーザーの表示名

レスポンスボディ:

FieldType説明
idstring一意のユーザー識別子
identityIdstringリンクされたアイデンティティ識別子
namestringユーザーの表示名
avatarobject or nullユーザーアバターメタデータまたはnull
createdAtstring作成タイムスタンプ
updatedAtstring最終更新タイムスタンプ

バリデーション:

  • スキーマバリデーション: 自動的に強制されます(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パラメータ:

ParameterType必須説明
profileIdstring一意のユーザープロフィール識別子

レスポンスボディ:

FieldType説明
idstring一意のユーザー識別子
identityIdstringリンクされたアイデンティティ識別子
namestringユーザーの表示名
avatarobject or nullユーザーアバターメタデータまたはnull
createdAtstring作成タイムスタンプ
updatedAtstring最終更新タイムスタンプ

バリデーション:

  • スキーマバリデーション: パスパラメータバリデーション(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トークンが必要(管理者のみ)

クエリパラメータ:

ParameterType必須説明
identityIdstringアイデンティティ識別子でユーザーをフィルタ
namestring表示名でユーザーをフィルタ
pagenumberページ番号(1-1000)
limitnumberページあたりの項目数(1-50)

レスポンスボディ:

FieldType説明
dataarrayユーザーオブジェクトの配列
metadataobjectレスポンスメタデータ
metadata.paginationobjectページネーション情報

data配列内の各ユーザーオブジェクトには以下が含まれます:

FieldType説明
idstring一意のユーザー識別子
identityIdstringリンクされたアイデンティティ識別子
namestringユーザーの表示名
avatarobject or nullユーザーアバターメタデータまたはnull
profileFollowsarrayプロフィールフォロー関係の配列
organizationFollowsarray組織フォロー関係の配列
productLikesarray商品いいね関係の配列
createdAtstring作成タイムスタンプ
updatedAtstring最終更新タイムスタンプ

バリデーション:

  • スキーマバリデーション: 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/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearerトークンが必要(管理者またはプロフィール所有者)

URLパラメータ:

ParameterType必須説明
profileIdstring一意のユーザープロフィール識別子

リクエストボディ(必須、すべてのフィールドはオプション):

FieldType必須説明
avatarobject or nullユーザーアバターメタデータまたはnull
namestringユーザーの表示名

注記: リクエストボディ内のすべてのフィールドはオプションですが、リクエストボディ自体は必須で、空にすることはできません。空のボディを送信すると400エラーが返されます。

レスポンスボディ:

FieldType説明
idstring一意のユーザー識別子
identityIdstringリンクされたアイデンティティ識別子
namestring更新されたユーザーの表示名
avatarobject or null更新されたユーザーアバターメタデータまたはnull
createdAtstring作成タイムスタンプ
updatedAtstring最終更新タイムスタンプ

バリデーション:

  • スキーマバリデーション: 自動的に強制されます(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パラメータ:

ParameterType必須説明
profileIdstring一意のユーザープロフィール識別子

レスポンスボディ:

FieldType説明
レスポンスボディなし-削除エンドポイントは成功時にレスポンスボディを返しません

バリデーション:

  • スキーマバリデーション: なし(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パラメータ:

ParameterType必須説明
profileIdstring対象ユーザープロフィールID

クエリパラメータ:

ParameterType必須説明
contentTypestring画像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
contentLengthnumberファイルサイズ(バイト単位、最大10MB = 10,000,000)

レスポンスボディ:

FieldType説明
objectIdstringアバター用に生成されたストレージオブジェクトID
urlstringファイルをアップロードするための事前署名付き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パラメータ:

ParameterType必須説明
identityIdstringプロフィールを取得する対象アイデンティティID

クエリパラメータ:

ParameterType必須Default説明
pagenumber1ページネーションのページ番号(1-1000)
limitnumber10ページあたりのプロフィール数(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パラメータ:

ParameterType必須説明
profileIdstringフォローを実行するプロフィールのID
followProfileIdstringフォローされるプロフィールの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パラメータ:

ParameterType必須説明
profileIdstringアンフォローを実行するプロフィールのID
followProfileIdstringアンフォローされるプロフィールの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パラメータ:

ParameterType必須説明
profileIdstringフォロワーを取得するプロフィールのID

クエリパラメータ:

ParameterType必須Default説明
pagenumber1ページネーションのページ番号(1-1000)
limitnumber20ページあたりの結果数(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パラメータ:

ParameterType必須説明
profileIdstringフォローを実行するプロフィールのID
followOrganizationIdstringフォローされる組織の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パラメータ:

ParameterType必須説明
profileIdstringフォローを削除するプロフィールのID
followOrganizationIdstringアンフォローされる組織の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): 商品にいいねするプロフィールのID
    • likeProductId (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): 商品のいいねを解除するプロフィールのID
    • likeProductId (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"
    • guest: ゲストユーザータイプ識別子
      • Type: string
      • 説明: ゲストユーザー用のカスタム識別子
      • ユースケース: 認証されていないまたは一時的なユーザー向けの限定アクセス
      • : "guest", "visitor", "anonymous"
    • regular: 通常ユーザータイプ識別子
      • Type: string
      • 説明: 通常ユーザー用のカスタム識別子
      • ユースケース: 標準的なユーザーアクセス権限
      • : "user", "member", "customer"

設定例

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形式で返されます:

一般的なエラーコード

StatusError Message説明
400Validation Error無効なリクエストボディ形式または必須フィールドの欠落
400Failed to create userデータベース挿入操作が挿入されたIDを返さなかった
400Failed to update user更新操作がデータを変更しなかった(変更が検出されなかった)
401token could not be verified認証トークンが欠落しているか無効
403Identity is not authorized to access this resource権限が不足しています
403User is not authorized to access this resourceユーザーに必要な権限がありません(管理者アクセス)
404User profile not foundGET/PATCH操作に対してユーザーが存在しません
404User not foundDELETE操作に対してユーザーが存在しません
500Failed to create user作成中のデータベース接続の問題または予期しない失敗
500Failed to get user取得中のデータベース接続の問題または予期しない失敗
500Failed to find usersリスト取得中のデータベース接続の問題、無効なフィルタ構文、または予期しない失敗
500Failed to update user更新中のデータベース接続の問題または予期しない失敗
500Failed 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'"
]
}
}

🔗 関連ドキュメント