monorepo/web/maplepress-frontend/docs/API/REGISTRATION_API.md

14 KiB

Registration API Implementation

This document describes the complete implementation of the user registration feature for the MaplePress frontend, integrated with the MaplePress backend API.

Overview

The registration feature allows new users to create an account and automatically sets up their tenant (organization) in a single step. Upon successful registration, users receive authentication tokens and are automatically logged in.

Backend API Endpoint

Endpoint: POST /api/v1/register Authentication: None required (public endpoint) Documentation: /cloud/maplepress-backend/docs/API.md (lines 66-166)

Request Structure

{
  "email": "user@example.com",
  "password": "SecurePassword123!",
  "confirm_password": "SecurePassword123!",
  "first_name": "John",
  "last_name": "Doe",
  "tenant_name": "Acme Corporation",
  "timezone": "America/New_York",
  "agree_terms_of_service": true,
  "agree_promotions": false,
  "agree_to_tracking_across_third_party_apps_and_services": false
}

Response Structure

{
  "user_id": "550e8400-e29b-41d4-a716-446655440000",
  "user_email": "user@example.com",
  "user_name": "John Doe",
  "user_role": "manager",
  "tenant_id": "650e8400-e29b-41d4-a716-446655440000",
  "tenant_name": "Acme Corporation",
  "tenant_slug": "acme-corp",
  "session_id": "750e8400-e29b-41d4-a716-446655440000",
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "access_expiry": "2024-10-24T12:00:00Z",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_expiry": "2024-11-24T00:00:00Z",
  "created_at": "2024-10-24T00:00:00Z"
}

Frontend Implementation

1. RegisterService (src/services/API/RegisterService.js)

Handles direct communication with the backend registration API.

Key Features:

  • Request validation (required fields, terms agreement)
  • Request body formatting (snake_case for backend)
  • Response transformation (camelCase for frontend)
  • User-friendly error message mapping
  • Tenant slug validation and generation utilities

Methods:

  • register(data) - Main registration method
  • validateTenantSlug(slug) - Validate slug format
  • generateTenantSlug(name) - Auto-generate slug from name

Usage:

import RegisterService from './services/API/RegisterService';

const response = await RegisterService.register({
  email: "user@example.com",
  password: "SecurePassword123!",
  confirmPassword: "SecurePassword123!",
  first_name: "John",
  last_name: "Doe",
  tenant_name: "Acme Corp",
  agree_terms_of_service: true,
});

2. AuthManager (src/services/Manager/AuthManager.js)

Manages authentication state, token storage, and session lifecycle.

Key Features:

  • Token management (access & refresh tokens)
  • LocalStorage persistence
  • Token expiry checking
  • User and tenant data storage
  • Session initialization and cleanup

New Methods:

  • register(registrationData) - Register and store auth data
  • storeAuthData(authResponse) - Store tokens and user data
  • clearSession() - Clear all auth data
  • isTokenExpired(expiry) - Check token expiry
  • getTenant() - Get current tenant information

Storage Keys:

maplepress_access_token
maplepress_refresh_token
maplepress_access_expiry
maplepress_refresh_expiry
maplepress_user
maplepress_tenant
maplepress_session_id

3. Register Page (src/pages/Auth/Register.jsx)

Complete registration form with all required fields.

Form Sections:

  1. Personal Information

    • First Name (required)
    • Last Name (required)
    • Email Address (required)
    • Password (required, min 8 chars)
    • Confirm Password (required)
  2. Organization Information

    • Organization Name (required, slug auto-generated by backend)
  3. Terms and Consent

    • Terms of Service agreement (required)
    • Promotional emails (optional)

Features:

  • Password match validation (backend-validated)
  • Terms of service requirement
  • Automatic timezone detection
  • Loading state during submission
  • RFC 9457 error message display with field-specific errors

Data Flow

User fills form
    ↓
Register.jsx validates data
    ↓
AuthManager.register(data)
    ↓
RegisterService.register(data)
    ↓
HTTP POST to /api/v1/register
    ↓
Backend validates and creates user + tenant
    ↓
Backend returns tokens and user data
    ↓
RegisterService transforms response
    ↓
AuthManager stores tokens in localStorage
    ↓
User redirected to /dashboard

Validation Rules

Frontend Validation

  1. Email: Required, valid email format
  2. Password:
    • Required
    • Minimum 8 characters
  3. Confirm Password:
    • Required
    • Must match password (validated by backend)
  4. Name: Required
  5. Tenant Name: Required
  6. Tenant Slug:
    • Required
    • Only lowercase letters, numbers, and hyphens
    • Validated by regex: /^[a-z0-9-]+$/
  7. Terms of Service: Must be checked

Backend Validation

Backend performs additional validation:

  • Email normalization and format validation
  • Password strength requirements (uppercase, lowercase, number, special char)
  • Password confirmation matching
  • Tenant slug uniqueness
  • Email uniqueness
  • No HTML in text fields
  • Input sanitization

Error Handling

RFC 9457 (Problem Details for HTTP APIs)

The backend returns validation errors in RFC 9457 format, which provides a structured, machine-readable error response.

Error Response Structure:

{
  "type": "about:blank",
  "title": "Validation Error",
  "status": 400,
  "detail": "One or more validation errors occurred",
  "errors": {
    "email": ["Invalid email format"],
    "password": ["Field is required", "Password must be at least 8 characters"],
    "confirm_password": ["Field is required", "Passwords do not match"],
    "first_name": ["Field is required"],
    "last_name": ["Field is required"],
    "tenant_name": ["Field is required"],
    "agree_terms_of_service": ["Must agree to terms of service"]
  }
}

Content-Type: application/problem+json

Key Fields:

  • type: URI reference identifying the problem type (uses about:blank for generic errors)
  • title: Short, human-readable summary of the error type
  • status: HTTP status code
  • detail: Human-readable explanation of the error
  • errors: Dictionary/map of field-specific validation errors (extension field)

Common Validation Errors

Field Error Message
email email: invalid email format
email email: email is required
password password: password is required
password password: password must be at least 8 characters
password password: password must contain at least one uppercase letter (A-Z)
password password: password must contain at least one lowercase letter (a-z)
password password: password must contain at least one number (0-9)
password password: password must contain at least one special character
confirm_password confirm_password: field is required
confirm_password confirm_password: passwords do not match
first_name first_name: field is required
first_name first_name: first_name must be between 1 and 100 characters
last_name last_name: field is required
last_name last_name: last_name must be between 1 and 100 characters
tenant_name tenant_name: tenant_name is required
tenant_name tenant_name: tenant_name must be between 1 and 100 characters
agree_terms_of_service agree_terms_of_service: must agree to terms of service

Frontend Error Parsing

The Register page component (src/pages/Auth/Register.jsx) includes a parseBackendError() function that:

  1. Checks if the error object contains RFC 9457 validationErrors structure
  2. Iterates through the errors dictionary and maps each field to its error messages
  3. Joins multiple error messages for the same field with semicolons
  4. Displays field-specific errors with red borders and inline messages
  5. Shows an error summary box at the top with all errors listed

Error Parsing Implementation:

const parseBackendError = (error) => {
  const fieldErrors = {};
  let generalError = null;

  // Check if error has RFC 9457 validation errors structure
  if (error.validationErrors && typeof error.validationErrors === 'object') {
    // Process each field's errors
    Object.entries(error.validationErrors).forEach(([fieldName, errorMessages]) => {
      if (Array.isArray(errorMessages) && errorMessages.length > 0) {
        // Join multiple error messages for the same field
        fieldErrors[fieldName] = errorMessages.join('; ');
      }
    });

    // Use the detail as general error if available
    if (error.message) {
      generalError = error.message;
    }
  } else {
    // Fallback for non-RFC 9457 errors
    generalError = error.message || "An error occurred. Please try again.";
  }

  return { fieldErrors, generalError };
};

Example Error Display:

When submitting an empty form, the user sees:

  • Error Summary Box: Lists all validation errors at the top of the form with the general message "One or more validation errors occurred"
  • Highlighted Fields: Red border on email, password, first_name, last_name, tenant_name, etc.
  • Inline Messages: Error text displayed below each affected field (e.g., "Field is required")

ApiClient Error Handling

The ApiClient (src/services/API/ApiClient.js) automatically parses RFC 9457 error responses and attaches the validation errors to the error object:

// Create error with RFC 9457 data if available
const error = new Error(
  errorData.detail || errorData.message || `HTTP ${response.status}: ${response.statusText}`
);

// Attach RFC 9457 fields to error for parsing
if (errorData.errors) {
  error.validationErrors = errorData.errors; // RFC 9457 validation errors
}
if (errorData.title) {
  error.title = errorData.title;
}
if (errorData.status) {
  error.status = errorData.status;
}

throw error;

Note: The frontend does not perform field validation - all validation, including password matching, is handled by the backend. The form submits whatever the user enters, and the backend returns comprehensive validation errors in RFC 9457 format.

Security Features

  1. Token Storage: Tokens stored in localStorage (client-side only)
  2. Token Expiry: Automatic expiry checking on initialization
  3. Password Validation: Client and server-side validation
  4. HTTPS Required: Production should use HTTPS
  5. Terms Agreement: Required before account creation
  6. Input Sanitization: Backend sanitizes all inputs

Testing the Registration Flow

1. Start Backend

cd cloud/mapleopentech-backend
task dev

2. Start Frontend

cd web/maplepress-frontend
npm run dev

3. Navigate to Registration

Open browser to: http://localhost:5173/register

4. Fill Form

  • First Name: John (required)
  • Last Name: Doe (required)
  • Email: test@example.com
  • Password: SecurePass123!
  • Confirm Password: SecurePass123!
  • Organization Name: Test Corp (slug auto-generated by backend)
  • Terms of Service: ✓ (checked)

5. Submit

Click "Create Account" button

6. Expected Result

  • Loading state appears
  • Request sent to backend
  • Tokens stored in localStorage
  • User redirected to /dashboard
  • Dashboard shows user information

7. Verify in Browser Console

// Check stored tokens
localStorage.getItem('maplepress_access_token')
localStorage.getItem('maplepress_user')
localStorage.getItem('maplepress_tenant')

// Check service instance
window.maplePressServices.authManager.isAuthenticated()
window.maplePressServices.authManager.getUser()
window.maplePressServices.authManager.getTenant()

Configuration

Environment Variables

Create .env file:

# Backend API URL
VITE_API_BASE_URL=http://localhost:8000

Production Configuration

For production:

VITE_API_BASE_URL=https://api.maplepress.io

Future Enhancements

Planned Features

  • Email verification flow
  • Password strength indicator
  • Captcha integration
  • Social authentication (Google, GitHub)
  • Organization logo upload
  • Custom domain support
  • Invitation codes/referrals
  • Account recovery flow

Security Improvements

  • CSRF token implementation
  • Rate limiting on frontend
  • Session fingerprinting
  • Two-factor authentication
  • Password breach checking
  • Secure token storage (HTTP-only cookies)

File Reference

Created Files

src/services/API/RegisterService.js

Modified Files

src/services/Manager/AuthManager.js
src/pages/Auth/Register.jsx

Backend Reference Files

cloud/maplepress-backend/docs/API.md
cloud/maplepress-backend/internal/interface/http/dto/gateway/register_dto.go
cloud/maplepress-backend/internal/interface/http/handler/gateway/register_handler.go

API Client Configuration

The ApiClient automatically handles:

  • JSON content-type headers
  • Request/response transformation
  • Error parsing
  • Authentication headers (for protected endpoints)

Base Configuration

API_CONFIG = {
  baseURL: import.meta.env.VITE_API_BASE_URL || "http://localhost:8000",
  timeout: 30000,
}

Support

For issues or questions:

  1. Check backend logs: docker logs mapleopentech_backend
  2. Check frontend console for errors
  3. Verify backend is running on port 8000
  4. Verify frontend environment variables
  5. Test backend endpoint directly with curl (see API.md)