🪪 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 tochannelIdin payloadsubscribedIdPathInPayload(optional): tuple path tosubscribedIdin 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 tosubscriptionIdin 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 tochannelIdin 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 tomessageIdin 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.
This validator is deprecated.
Replacement: ownsChannel.
Purpose: Ensures users have proper channel ownership and permissions
Parameters:
allowedSubjects:string[]- Array of allowed user types/subjectsauthenticate: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.channelIdpayload.params.requestParams.channelIdpayload.params.requestQuery.channelIdpayload.params.requestBody.channelId
Owner ID Sources (for new channels):
payload.context.data.ownerIdpayload.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.
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.messageIdpayload.params.requestParams.messageIdpayload.params.requestQuery.messageIdpayload.params.requestBody.messageId
Sender ID Sources (for new messages):
payload.context.data.senderIdpayload.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'])
]
});
🔗 Related Documentation
- Chat Schemas - Chat data validation and contracts
- Chat Handlers - Chat business logic functions
- Chat Routes - Chat HTTP endpoint definitions
- Chat Features - Chat composed features