@hsuite/users-types - User Type Definitions

👥 Comprehensive TypeScript library for user management with full NestJS and MongoDB integration

Type-safe user entity definitions, interfaces, and models providing robust user data structures with built-in validation, authentication integration, and complete NestJS ecosystem support.


📚 Table of Contents


✨ Quick Start

Installation

npm install @hsuite/users-types

Basic Setup

import { User, IUser } from '@hsuite/users-types';

// Type-safe user entity
const user: User.Safe = {
  email: "[email protected]",
  username: "johndoe",
  created_at: Date.now(),
  updated_at: Date.now(),
  confirmed: true,
  type: "standard",
  role: "user",
  tags: ["premium", "beta"],
  banned: false,
  twoFactorAuth: {
    enabled: false,
    secret: null,
    backupCodes: []
  }
};

NestJS Integration

import { Schema, SchemaFactory } from '@nestjs/mongoose';
import { User } from '@hsuite/users-types';

@Schema({ collection: 'users', timestamps: true })
export class UserEntity extends User.Safe {
  @Prop({ auto: true })
  _id: string;
}

export const UserSchema = SchemaFactory.createForClass(UserEntity);

🏗️ Architecture

Type System Structure

The library is organized around two primary namespaces:

🔧 IUser Namespace

  • Interface Definitions - Foundation for user-related type definitions

  • Type Safety - Strict TypeScript interfaces for user entities

  • Extensibility - Framework for future interface additions

👤 User Namespace

  • Concrete Models - Implementation classes with full validation

  • MongoDB Integration - Ready-to-use Mongoose schemas

  • API Documentation - Complete Swagger/OpenAPI decorators

Core Components

🛡️ User.Safe Class

  • Public Properties - Safe user data representation

  • Full Validation - Built-in email and role validation

  • Auth Integration - Seamless compatibility with HSuite auth system

  • Database Ready - Complete Mongoose decorators and constraints

🔐 Authentication Types

  • Role-Based Access - User, admin, and owner role definitions

  • Two-Factor Auth - Complete 2FA type structures

  • User Types - Extensible user account type system

  • Permission Integration - Compatible with HSuite permission systems

Module Structure

src/
├── interfaces/
│   └── types.namespace.ts     # IUser namespace definitions
├── models/
│   └── types.namespace.ts     # User model implementations
└── index.ts                   # Main export file

🔧 API Reference

User.Safe Class

Core Properties

Property
Type
Required
Description
Validation

email

string

User's email address

Unique, email format

username

string

Unique username

Required

created_at

number

Account creation timestamp

Unix timestamp

updated_at

number

Last update timestamp

Unix timestamp

confirmed

boolean

Account confirmation status

Boolean flag

type

IAuth.ICredentials.IUser.IType

User account type

Auth type

role

'user' | 'admin' | 'owner'

User system role

Role enum

tags

Array<Auth.Credentials.User.Tags>

User categorization tags

Optional array

banned

boolean

Ban status flag

Optional boolean

twoFactorAuth

Auth.TwoFactor.Auth

2FA configuration

Auth object

Property Details

email: string

  • Validation: Email format validation using validator/lib/isEmail

  • Constraints: Unique across the system

  • Usage: Primary user identification and communication

username: string

  • Validation: Required field validation

  • Constraints: Unique username requirement

  • Usage: User-friendly identification

  • Example: "johndoe"

role: 'user' | 'admin' | 'owner'

  • Type Safety: Strict union type enforcement

  • Permissions: Determines system access levels

  • Integration: Compatible with HSuite RBAC system

  • Default: "user"

twoFactorAuth: Auth.TwoFactor.Auth

  • Integration: Full compatibility with @hsuite/auth-types

  • Features: Secret management, backup codes, enabled status

  • Security: Enterprise-grade 2FA implementation

  • Structure: Complete authentication configuration

Namespaces

IUser Namespace

export namespace IUser {
  // Foundation for future interface definitions
}

User Namespace

export namespace User {
  export class Safe implements IAuth.ICredentials.IUser.IEntity {
    // Complete implementation with decorators
  }
}

Decorator Reference

Mongoose Decorators

@Prop({
  unique: true,
  required: true,
  type: String,
  validate: [isEmail, 'invalid email']
})
email: string;

Swagger Decorators

@ApiProperty({
  type: String,
  description: 'Email address used for user identification',
  required: true,
  example: '[email protected]'
})
email: string;

📖 Guides

User Schema Setup Guide

Configure MongoDB schemas using User.Safe class definitions. Comprehensive setup guide covering MongoDB schema configuration, type validation, data modeling, field mapping, and enterprise-grade user data management with complete type safety and validation.

Authentication Integration Guide

Integrate user types with HSuite authentication system. Advanced integration guide covering authentication workflows, user credential management, session handling, role-based access control, and secure user authentication with comprehensive security features.

API Documentation Guide

Generate comprehensive API documentation with Swagger. Detailed documentation guide covering Swagger integration, API endpoint documentation, type definitions, request/response examples, and enterprise-grade API documentation for user management systems.


🎯 Examples

Basic User Management

import { User } from '@hsuite/users-types';
import { IAuth } from '@hsuite/auth-types';

@Injectable()
export class UserManagementService {
  
  async createUser(userData: Partial<User.Safe>): Promise<User.Safe> {
    const user: User.Safe = {
      email: userData.email,
      username: userData.username,
      created_at: Date.now(),
      updated_at: Date.now(),
      confirmed: false,
      type: 'standard' as IAuth.ICredentials.IUser.IType,
      role: 'user',
      tags: [],
      banned: false,
      twoFactorAuth: {
        enabled: false,
        secret: null,
        backupCodes: []
      }
    };

    return user;
  }

  validateUserRole(user: User.Safe, requiredRole: 'user' | 'admin' | 'owner'): boolean {
    const roleHierarchy = {
      'user': 0,
      'admin': 1,
      'owner': 2
    };

    return roleHierarchy[user.role] >= roleHierarchy[requiredRole];
  }

  updateUserTags(user: User.Safe, newTags: string[]): User.Safe {
    return {
      ...user,
      tags: newTags,
      updated_at: Date.now()
    };
  }
}

NestJS Service Implementation

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User } from '@hsuite/users-types';

@Schema({ collection: 'users', timestamps: true })
export class UserDocument extends User.Safe {
  @Prop({ auto: true })
  _id: string;
}

export const UserSchema = SchemaFactory.createForClass(UserDocument);

@Injectable()
export class UsersService {
  constructor(
    @InjectModel('User') private userModel: Model<UserDocument>
  ) {}

  async createUser(createUserDto: Partial<User.Safe>): Promise<UserDocument> {
    try {
      const user = new this.userModel({
        ...createUserDto,
        created_at: Date.now(),
        updated_at: Date.now(),
        confirmed: false,
        banned: false,
        twoFactorAuth: {
          enabled: false,
          secret: null,
          backupCodes: []
        }
      });

      const savedUser = await user.save();
      return savedUser;
    } catch (error) {
      if (error.code === 11000) {
        throw new Error('Email already exists');
      }
      throw error;
    }
  }

  async findUserByEmail(email: string): Promise<UserDocument | null> {
    return await this.userModel.findOne({ email }).exec();
  }

  async updateUser(
    userId: string, 
    updateData: Partial<User.Safe>
  ): Promise<UserDocument> {
    const updatedUser = await this.userModel.findByIdAndUpdate(
      userId,
      {
        ...updateData,
        updated_at: Date.now()
      },
      { new: true, runValidators: true }
    ).exec();

    if (!updatedUser) {
      throw new Error('User not found');
    }

    return updatedUser;
  }

  async banUser(userId: string): Promise<UserDocument> {
    return await this.updateUser(userId, { banned: true });
  }

  async confirmUser(userId: string): Promise<UserDocument> {
    return await this.updateUser(userId, { confirmed: true });
  }

  async getUsersByRole(role: 'user' | 'admin' | 'owner'): Promise<UserDocument[]> {
    return await this.userModel.find({ role }).exec();
  }

  async searchUsersByTags(tags: string[]): Promise<UserDocument[]> {
    return await this.userModel.find({
      tags: { $in: tags }
    }).exec();
  }
}

API Controller with Swagger Documentation

import { Controller, Get, Post, Body, Param, Put } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from '@nestjs/swagger';
import { User } from '@hsuite/users-types';
import { UsersService } from './users.service';

@ApiTags('Users')
@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  @ApiOperation({ summary: 'Create new user' })
  @ApiResponse({ 
    status: 201, 
    description: 'User created successfully',
    type: User.Safe
  })
  @ApiResponse({ 
    status: 400, 
    description: 'Invalid user data or email already exists'
  })
  async createUser(@Body() userData: Partial<User.Safe>): Promise<User.Safe> {
    return await this.usersService.createUser(userData);
  }

  @Get(':email')
  @ApiOperation({ summary: 'Get user by email' })
  @ApiParam({ name: 'email', description: 'User email address' })
  @ApiResponse({ 
    status: 200, 
    description: 'User found',
    type: User.Safe
  })
  @ApiResponse({ 
    status: 404, 
    description: 'User not found'
  })
  async getUserByEmail(@Param('email') email: string): Promise<User.Safe> {
    const user = await this.usersService.findUserByEmail(email);
    if (!user) {
      throw new Error('User not found');
    }
    return user;
  }

  @Put(':id/ban')
  @ApiOperation({ summary: 'Ban user account' })
  @ApiParam({ name: 'id', description: 'User ID' })
  @ApiResponse({ 
    status: 200, 
    description: 'User banned successfully',
    type: User.Safe
  })
  async banUser(@Param('id') userId: string): Promise<User.Safe> {
    return await this.usersService.banUser(userId);
  }

  @Put(':id/confirm')
  @ApiOperation({ summary: 'Confirm user account' })
  @ApiParam({ name: 'id', description: 'User ID' })
  @ApiResponse({ 
    status: 200, 
    description: 'User confirmed successfully',
    type: User.Safe
  })
  async confirmUser(@Param('id') userId: string): Promise<User.Safe> {
    return await this.usersService.confirmUser(userId);
  }

  @Get('role/:role')
  @ApiOperation({ summary: 'Get users by role' })
  @ApiParam({ 
    name: 'role', 
    description: 'User role',
    enum: ['user', 'admin', 'owner']
  })
  @ApiResponse({ 
    status: 200, 
    description: 'Users retrieved successfully',
    type: [User.Safe]
  })
  async getUsersByRole(
    @Param('role') role: 'user' | 'admin' | 'owner'
  ): Promise<User.Safe[]> {
    return await this.usersService.getUsersByRole(role);
  }
}

Authentication Integration

import { Injectable } from '@nestjs/common';
import { User } from '@hsuite/users-types';
import { IAuth } from '@hsuite/auth-types';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthenticationService {
  constructor(private jwtService: JwtService) {}

  /**
   * Validates user authentication and returns safe user data
   */
  validateUserCredentials(user: User.Safe): IAuth.ICredentials.IUser.IEntity {
    if (user.banned) {
      throw new Error('User account is banned');
    }

    if (!user.confirmed) {
      throw new Error('User account not confirmed');
    }

    // User.Safe implements IAuth.ICredentials.IUser.IEntity
    return user;
  }

  /**
   * Generates JWT token with user information
   */
  generateUserToken(user: User.Safe): string {
    const payload = {
      email: user.email,
      username: user.username,
      role: user.role,
      type: user.type,
      confirmed: user.confirmed
    };

    return this.jwtService.sign(payload);
  }

  /**
   * Validates user permissions based on role
   */
  validateUserPermissions(
    user: User.Safe,
    requiredPermissions: string[]
  ): boolean {
    const rolePermissions = {
      'user': ['read:own', 'update:own'],
      'admin': ['read:all', 'update:all', 'create:all'],
      'owner': ['read:all', 'update:all', 'create:all', 'delete:all']
    };

    const userPermissions = rolePermissions[user.role] || [];
    return requiredPermissions.every(permission => 
      userPermissions.includes(permission)
    );
  }

  /**
   * Enables two-factor authentication for user
   */
  async enableTwoFactor(
    user: User.Safe,
    secret: string,
    backupCodes: string[]
  ): Promise<User.Safe> {
    return {
      ...user,
      twoFactorAuth: {
        enabled: true,
        secret: secret,
        backupCodes: backupCodes
      },
      updated_at: Date.now()
    };
  }
}

User Validation Utilities

import { User } from '@hsuite/users-types';
import { validate } from 'class-validator';
import isEmail from 'validator/lib/isEmail';

export class UserValidationUtils {
  
  /**
   * Validates user email format
   */
  static validateEmail(email: string): boolean {
    return isEmail(email);
  }

  /**
   * Validates username format
   */
  static validateUsername(username: string): boolean {
    const usernameRegex = /^[a-zA-Z0-9_]{3,20}$/;
    return usernameRegex.test(username);
  }

  /**
   * Validates user role
   */
  static validateRole(role: string): role is 'user' | 'admin' | 'owner' {
    return ['user', 'admin', 'owner'].includes(role);
  }

  /**
   * Validates complete user object
   */
  static async validateUser(user: User.Safe): Promise<{
    isValid: boolean;
    errors: string[];
  }> {
    const errors: string[] = [];

    // Email validation
    if (!this.validateEmail(user.email)) {
      errors.push('Invalid email format');
    }

    // Username validation
    if (!this.validateUsername(user.username)) {
      errors.push('Invalid username format (3-20 alphanumeric characters and underscores)');
    }

    // Role validation
    if (!this.validateRole(user.role)) {
      errors.push('Invalid user role');
    }

    // Required fields validation
    if (!user.created_at || !user.updated_at) {
      errors.push('Missing required timestamp fields');
    }

    if (user.confirmed === undefined || user.confirmed === null) {
      errors.push('Missing confirmation status');
    }

    return {
      isValid: errors.length === 0,
      errors
    };
  }

  /**
   * Sanitizes user data for safe exposure
   */
  static sanitizeUserForPublic(user: User.Safe): Partial<User.Safe> {
    return {
      email: user.email,
      username: user.username,
      role: user.role,
      confirmed: user.confirmed,
      tags: user.tags,
      created_at: user.created_at
      // Exclude sensitive fields like twoFactorAuth
    };
  }
}

Testing Utilities

import { User } from '@hsuite/users-types';
import { IAuth } from '@hsuite/auth-types';

export class UserTestingUtils {
  
  /**
   * Creates a mock user for testing
   */
  static createMockUser(overrides: Partial<User.Safe> = {}): User.Safe {
    const defaultUser: User.Safe = {
      email: '[email protected]',
      username: 'testuser',
      created_at: Date.now(),
      updated_at: Date.now(),
      confirmed: true,
      type: 'standard' as IAuth.ICredentials.IUser.IType,
      role: 'user',
      tags: [],
      banned: false,
      twoFactorAuth: {
        enabled: false,
        secret: null,
        backupCodes: []
      }
    };

    return { ...defaultUser, ...overrides };
  }

  /**
   * Creates multiple mock users for testing
   */
  static createMockUsers(count: number): User.Safe[] {
    return Array.from({ length: count }, (_, index) => 
      this.createMockUser({
        email: `test${index}@example.com`,
        username: `testuser${index}`
      })
    );
  }

  /**
   * Creates admin user for testing
   */
  static createMockAdmin(): User.Safe {
    return this.createMockUser({
      email: '[email protected]',
      username: 'admin',
      role: 'admin'
    });
  }

  /**
   * Creates owner user for testing
   */
  static createMockOwner(): User.Safe {
    return this.createMockUser({
      email: '[email protected]',
      username: 'owner',
      role: 'owner'
    });
  }
}

🔗 Integration

Required Dependencies

{
  "@nestjs/common": "^10.4.2",
  "@nestjs/core": "^10.4.2",
  "@hsuite/auth-types": "^2.1.2",
  "@hsuite/nestjs-swagger": "^1.0.3",
  "@nestjs/mongoose": "^10.0.0",
  "mongoose": "^8.0.0",
  "validator": "^13.0.0",
  "class-validator": "^0.14.0"
}

TypeScript Configuration

{
  "compilerOptions": {
    "declaration": true,
    "outDir": "../../dist/libs/users-types",
    "types": ["node"],
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "test", "**/*spec.ts"]
}

Module Integration

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { User } from '@hsuite/users-types';

// Create schema from User.Safe class
@Schema({ collection: 'users', timestamps: true })
export class UserDocument extends User.Safe {}

export const UserSchema = SchemaFactory.createForClass(UserDocument);

@Module({
  imports: [
    MongooseModule.forFeature([
      { name: 'User', schema: UserSchema }
    ])
  ],
  providers: [UsersService],
  controllers: [UsersController],
  exports: [UsersService]
})
export class UsersModule {}

Documentation Generation

# Generate comprehensive documentation
npm run compodoc

# Generate documentation with coverage report
npm run compodoc:coverage

Integration with HSuite Ecosystem

// Complete integration with other HSuite modules
import { User } from '@hsuite/users-types';
import { IAuth } from '@hsuite/auth-types';
import { AuthModule } from '@hsuite/auth';
import { SmartConfigModule } from '@hsuite/smart-config';

@Module({
  imports: [
    AuthModule,
    SmartConfigModule,
    MongooseModule.forFeature([
      { name: 'User', schema: UserSchema }
    ])
  ]
})
export class UserManagementModule {}

@Injectable()
export class IntegratedUserService {
  constructor(
    private authService: AuthService,
    private usersService: UsersService
  ) {}

  async createAuthenticatedUser(
    userData: Partial<User.Safe>,
    session: IAuth.ICredentials.IWeb3.IEntity
  ): Promise<User.Safe> {
    // Validate session permissions
    const hasPermission = await this.authService.validatePermission(
      session, 
      'user:create'
    );

    if (!hasPermission) {
      throw new Error('Insufficient permissions to create user');
    }

    // Create user with type safety
    const user = await this.usersService.createUser(userData);
    
    return user;
  }
}

👥 Type-Safe User Management: Comprehensive TypeScript definitions with full validation and authentication integration.

🛡️ Enterprise Security: Role-based access control, two-factor authentication, and complete audit trail support.

🔧 Developer Experience: Full NestJS integration with Mongoose schemas and automatic API documentation generation.


Built with ❤️ by the HbarSuite Team Copyright © 2024 HbarSuite. All rights reserved.

Last updated