メインコンテンツまでスキップ
バージョン: 🚧 Canary

🪪 Chat Validators

Chat validators provide validation functions for chat-related operations in Nodeblocks applications. These validators ensure proper access control and data validation for chat channels, messages, and conversations.


🎯 Overview

Chat validators are designed to:

  • Validate channel access based on ownership and permissions
  • Ensure proper message access for chat operations
  • Support multiple access patterns (owner, admin, member)
  • Handle chat-specific validation logic for secure operations
  • Provide reusable validation for chat workflows

📋 Chat Validator Types

Access Control Validators

Validators that check user permissions for chat resources.


🔧 Available Chat Validators

hasSubscription

Validates that the identity is subscribed to the specified channel.

Purpose: Ensures a user is subscribed to a channel before accessing related resources

Parameters:

  • channelIdPathInPayload: tuple path to channelId in payload
  • subscribedIdPathInPayload (optional): tuple path to subscribedId in payload; defaults to authenticated identity

Returns: void - Passes through if a subscription exists

Throws:

  • NodeblocksError (500) with message "db.subscriptions is not set"
  • NodeblocksError (401) with message "Invalid token"
  • NodeblocksError (400) with message "Invalid channel ID"
  • NodeblocksError (400) with message "Invalid subscribed ID"
  • NodeblocksError (500) with message "Failed to fetch subscription"
  • NodeblocksError (403) with message "Identity is not subscribed to the channel"

Usage:

import { validators } from '@nodeblocks/backend-sdk';

const { hasSubscription } = validators;

withRoute({
-- snip --
validators: [
hasSubscription(['requestParams', 'channelId'])
]
});

ownsSubscription

Subscription ownership validator for authenticated user access.

Purpose: Ensures only the subscription owner (subscribed identity) can modify the subscription

Parameters:

  • resourceIdPathInPayload: tuple path to subscriptionId in payload (e.g. ['requestParams', 'subscriptionId'])

Returns: void - Passes through if the authenticated identity owns the subscription

Throws:

  • NodeblocksError (401) with message "Invalid token"
  • NodeblocksError (500) with message "Resource does not exist"
  • NodeblocksError (400) with message "Invalid resource ID"
  • NodeblocksError (403) with message "Failed to fetch resource"
  • NodeblocksError (403) with message "Invalid owner ID"
  • NodeblocksError (403) with message "Identity is not the owner of the resource"

Usage:

import { validators } from '@nodeblocks/backend-sdk';

const { ownsSubscription } = validators;

withRoute({
-- snip --
validators: [
ownsSubscription(['requestParams', 'subscriptionId'])
]
});

ownsChannel

Chat channel ownership validator for authenticated user access.

Purpose: Ensures only the channel owner can access/modify the channel

Parameters:

  • resourceIdPathInPayload: tuple path to channelId in payload (e.g. ['requestParams', 'channelId'])

Returns: void - Passes through if the authenticated identity owns the channel

Throws:

  • NodeblocksError (401) with message "Invalid token"
  • NodeblocksError (500) with message "Resource does not exist"
  • NodeblocksError (400) with message "Invalid resource ID"
  • NodeblocksError (403) with message "Failed to fetch resource"
  • NodeblocksError (403) with message "Invalid owner ID"
  • NodeblocksError (403) with message "Identity is not the owner of the resource"

Usage:

import { validators } from '@nodeblocks/backend-sdk';

const { ownsChannel } = validators;

withRoute({
-- snip --
validators: [
ownsChannel(['requestParams', 'channelId'])
]
});

ownsMessage

Chat message ownership validator for authenticated user access.

Purpose: Ensures only the message sender can access/modify the message

Parameters:

  • resourceIdPathInPayload: tuple path to messageId in payload (e.g. ['requestParams', 'messageId'])

Returns: void - Passes through if the authenticated identity is the sender

Throws:

  • NodeblocksError (401) with message "Invalid token"
  • NodeblocksError (500) with message "Resource does not exist"
  • NodeblocksError (400) with message "Invalid resource ID"
  • NodeblocksError (403) with message "Failed to fetch resource"
  • NodeblocksError (403) with message "Invalid owner ID"
  • NodeblocksError (403) with message "Identity is not the owner of the resource"

Usage:

import { validators } from '@nodeblocks/backend-sdk';

const { ownsMessage } = validators;

withRoute({
-- snip --
validators: [
ownsMessage(['requestParams', 'messageId'])
]
});

validateChannelAccess

Validates channel access based on allowed subjects and token information.

Deprecated

This validator is deprecated.
Replacement: ownsChannel.

Purpose: Ensures users have proper channel ownership and permissions

Parameters:

  • allowedSubjects: string[] - Array of allowed user types/subjects
  • authenticate: Authenticator - Authentication function (optional, defaults to getBearerTokenInfo)
  • payload: RouteHandlerPayload - Contains request context and data

Returns: void - Passes through if user has appropriate permissions

Throws:

  • NodeblocksError (401) with message "App token is not valid" or "User token is not valid" for invalid tokens
  • NodeblocksError (400) with message "must have ownerId when creating a new channel" for missing ownerId on new channels
  • NodeblocksError (403) with message "Channel has no owner" for channels without owner
  • NodeblocksError (403) with message "User is not authorized to access this channel" for unauthorized access
  • NodeblocksError (404) with message "Channel not found" if channel doesn't exist
  • NodeblocksError (401) with message "Token does not have a valid access type" for invalid token types

Supported Subjects:

  • 'owner' - Channel owner access

Channel ID Sources (checked in order):

  • payload.context.data.channelId
  • payload.params.requestParams.channelId
  • payload.params.requestQuery.channelId
  • payload.params.requestBody.channelId

Owner ID Sources (for new channels):

  • payload.context.data.ownerId
  • payload.params.requestBody.ownerId

Usage:

import { validators } from '@nodeblocks/backend-sdk';

const { validateChannelAccess } = validators;

withRoute({
-- snip --
validators: [validateChannelAccess(['owner'])]
});
withRoute({
-- snip --
validators: [validateChannelAccess(['owner', 'admin'])]
});

validateMessageAccess

Validates message access based on allowed subjects and token information.

Deprecated

This validator is deprecated.
Replacement: ownsMessage.

Purpose: Ensures users have proper message ownership and permissions

Parameters:

  • allowedSubjects: string[] - Array of allowed user types/subjects (e.g., ['owner'])
  • authenticate: Authenticator - Authentication function (optional, defaults to getBearerTokenInfo)
  • payload: RouteHandlerPayload - Contains request context and data

Returns: void - Passes through if user has appropriate permissions

Throws:

  • NodeblocksError (401) with message "App token is not valid" or "User token is not valid" for invalid tokens
  • NodeblocksError (400) with message "must have senderId when creating a new message" for missing senderId on new messages
  • NodeblocksError (403) with message "Message has no sender" for messages without sender
  • NodeblocksError (403) with message "User is not authorized to access this message" for unauthorized access
  • NodeblocksError (404) with message "Message not found" if message doesn't exist
  • NodeblocksError (401) with message "Token does not have a valid access type" for invalid token types

Supported Subjects:

  • 'owner' - Message sender access

Message ID Sources (checked in order):

  • payload.context.data.messageId
  • payload.params.requestParams.messageId
  • payload.params.requestQuery.messageId
  • payload.params.requestBody.messageId

Sender ID Sources (for new messages):

  • payload.context.data.senderId
  • payload.params.requestBody.senderId

Usage:

import { validators } from '@nodeblocks/backend-sdk';

const { validateMessageAccess } = validators;

// Message sender access
withRoute({
-- snip --
validators: [validateMessageAccess(['owner'])]
});

// Message sender or admin access
withRoute({
-- snip --
validators: [validateMessageAccess(['owner', 'admin'])]
});

hasOrganizationAccessToMessageTemplate

Validates organization member access to chat message templates based on allowed roles and a template ID.

Purpose: Ensures the authenticated identity is a member of the template's organization with an allowed role

Parameters:

  • allowedRoles: string[] - Allowed organization roles, e.g. ['owner','admin']
  • messageTemplateIdPathInPayload - Tuple path to the template ID, e.g. ['requestParams','messageTemplateId']

Returns: void - Passes if access is allowed; otherwise throws

Throws:

  • NodeblocksError (401) with message "Invalid token"
  • NodeblocksError (500) with message "Chat message templates collection is not set"
  • NodeblocksError (404) with message "Chat message template not found"
  • NodeblocksError (403) with message "Must be an admin to access this resource" (template without organizationId)
  • NodeblocksError (500) with message "Organizations collection is not set"
  • NodeblocksError (404) with message "Organization not found"
  • NodeblocksError (403) with message "Identity is not allowed access to this resource"

Usage:

import { validators } from '@nodeblocks/backend-sdk';

const { hasOrganizationAccessToMessageTemplate } = validators;

withRoute({
// ...
validators: [
hasOrganizationAccessToMessageTemplate(
['owner','admin'],
['requestParams','messageTemplateId']
)
]
});

channelExists

Validates that a chat channel exists in the database.

Purpose: Ensures a channel exists before allowing operations on it

Parameters:

  • channelIdPathInPayload: [T, ...T[]] - Tuple path array to extract channel ID from request payload (e.g., ['params', 'requestParams', 'channelId'])

Returns: void - Passes through if channel exists

Throws:

  • NodeblocksError (500) with message "Missing channel collection" if chatChannels collection is not configured
  • NodeblocksError (500) with message "Unknown db error" for database operation failures
  • NodeblocksError (404) with message "Channel does not exist" if channel is not found

Handler Process:

  • Input: RouteHandlerPayload with database context and channel ID path in payload
  • Process: Extracts channel ID from payload using provided path, queries database for channel existence
  • Output: Throws NodeblocksError if validation fails; continues if channel exists
  • Errors: 500 for missing collection or database errors, 404 if channel doesn't exist

Usage:

import { validators } from '@nodeblocks/backend-sdk';

const { channelExists } = validators;

// Used in route composition:
withRoute({
handler: compose(channelHandler),
validators: [
isAuthenticated(),
channelExists(['params', 'requestParams', 'channelId'])
]
});

Example Scenarios:

// Validating channel for read state updates:
withRoute({
method: 'PUT',
path: '/channels/:channelId/read-state',
validators: [
isAuthenticated(),
channelExists(['params', 'requestParams', 'channelId']),
hasSubscription(['params', 'requestParams', 'channelId'])
]
});

// Validating channel for subscription operations:
withRoute({
method: 'POST',
path: '/channels/:channelId/subscriptions',
validators: [
isAuthenticated(),
channelExists(['params', 'requestParams', 'channelId'])
]
});