Skip to Content
Term Policy Document

Term Policy Document

Overview

The Term Policy module manages legal agreements and user consent within the application. It provides a complete workflow for creating, versioning, managing, and enforcing user acceptance of legal policies such as terms of service, privacy policies, marketing consents, and cookie policies.

Table of Contents

Policy Types

Four policy types are available via EnumTermPolicyType:

TypeDescription
termsOfServiceTerms of Service agreement
privacyPrivacy Policy
marketingMarketing consent
cookiesCookie Policy

Each type can have multiple versions. Users must accept the latest published version to access protected endpoints.

Policy Status

Term policies follow a two-stage status:

Draft Status

  • Policy created by admin
  • Content files stored in private S3 bucket
  • Can be edited, updated, or deleted
  • Not visible to users
  • Path: {uploadContentPath}/{type}/{version}/{language}.hbs

Published Status

  • Policy published by admin
  • Content files moved to public S3 bucket
  • Cannot be edited or deleted
  • Visible to all users
  • Invalidates all existing user acceptances for that policy type
  • All active users must re-accept the new version
  • Path: {contentPublicPath}/{type}/{version}/{language}.hbs

Important: When a new version is published, all users termPolicy[type] flags are set to false, requiring them to accept the new version before accessing protected endpoints.

Flow

Admin Flow Diagram

User Flow Diagram

User Endpoints

Users interact with term policies through acceptance and viewing their acceptance history.

List Published Policies

Users can view all published policies available for acceptance:

GET /term-policy/list

Returns policies with cursor pagination, optionally filtered by type.

Accept Policy

To accept a specific policy type:

POST /user/term-policy/accept { "type": "termsOfService" }

View Acceptance History

Users can view their acceptance history:

GET /user/term-policy/list/accepted

Returns all policies the user has accepted with timestamps and policy details.

Admin Endpoints

Admins manage the complete lifecycle of term policies from creation to publishing.

Generate Presign URL

Generate presigned URL for uploading content to S3:

POST /term-policy/generate/content/presign

Create Policy

Create new policy with initial content:

POST /term-policy/create

Add Content

Add new language variant to draft policy:

PUT /term-policy/update/:termPolicyId/content/add

Update Content

Replace existing language content in draft policy:

PUT /term-policy/update/:termPolicyId/content/update

Remove Content

Remove specific language variant from draft policy:

DELETE /term-policy/update/:termPolicyId/content/remove

Get Content

Get presigned URL to download policy content:

POST /term-policy/get/:termPolicyId/content/:language

Publish Policy

Publish policy and invalidate all user acceptances:

PATCH /term-policy/publish/:termPolicyId

Critical: Publishing sets termPolicy[type] to false for all users, requiring re-acceptance. Once published, policy cannot be edited or deleted.

List Policies

List all policies with optional filters:

GET /term-policy/list?type=termsOfService&status=draft

Delete Policy

Delete draft policy and remove S3 content:

DELETE /term-policy/delete/:termPolicyId

Only draft policies can be deleted.

TermPolicyAcceptanceProtected

The @TermPolicyAcceptanceProtected() decorator protects endpoints by requiring users to accept specific policies before accessing them.

Important: This decorator requires both @UserProtected() and @AuthJwtAccessProtected() to be applied. Without these decorators, the endpoint will return a 403 Forbidden error.

Decorator order (from top to bottom):

@TermPolicyAcceptanceProtected() @UserProtected() @AuthJwtAccessProtected()

Basic Usage

@Controller('user') export class UserController { // Requires termsOfService acceptance @TermPolicyAcceptanceProtected(EnumTermPolicyType.termsOfService) @UserProtected() @AuthJwtAccessProtected() @Get('/profile') async getProfile() { return { message: 'Profile data' }; } // Requires both termsOfService and privacy acceptance @TermPolicyAcceptanceProtected( EnumTermPolicyType.termsOfService, EnumTermPolicyType.privacy ) @UserProtected() @AuthJwtAccessProtected() @Get('/settings') async getSettings() { return { message: 'Settings data' }; } // Requires marketing consent @TermPolicyAcceptanceProtected(EnumTermPolicyType.marketing) @UserProtected() @AuthJwtAccessProtected() @Get('/newsletter') async getNewsletter() { return { message: 'Newsletter content' }; } // Default: requires termsOfService and privacy @TermPolicyAcceptanceProtected() @UserProtected() @AuthJwtAccessProtected() @Get('/dashboard') async getDashboard() { return { message: 'Dashboard data' }; } }

How It Works

Important Notes

  • @TermPolicyAcceptanceProtected() requires @UserProtected() and @AuthJwtAccessProtected() to be applied
  • Decorator order from top to bottom: @TermPolicyAcceptanceProtected()@UserProtected()@AuthJwtAccessProtected()
  • For more details about @AuthJwtAccessProtected(), see Authentication Documentation
  • For more details about @UserProtected(), see Authorization Documentation
  • Without the required decorators, the endpoint will throw a 403 Forbidden error
  • If no term policies are specified, it defaults to requiring termsOfService and privacy acceptance
  • All specified term policies must be accepted by the user for access to be granted
  • Incorrect decorator ordering will result in runtime errors

Migration & Seeding

Template migration seed available at:

src/migration/seeds/migration.template-term-policy.seed.ts

This seed file provides:

  • Sample term policies for all types
  • Multi-language content examples
  • Published policy setup

For detailed migration and seeding instructions, see Database Documentation.

Contribution

Special thanks to [Gzerox][ref-contributor-gzerox] for contributing to the Term Policy module implementation.

Last updated on