/**
* Organization Controller Layer
*
* This controller handles HTTP requests and responses for organization operations.
* It serves as the interface between the HTTP layer and the organization service,
* managing request validation, response formatting, and error handling.
*
* Key responsibilities:
* - HTTP request/response handling
* - Input validation and sanitization
* - Error response formatting
* - Service layer coordination
* - Status code management
*
* Authentication requirements:
* - Most endpoints require admin privileges
* - Data updates require employee privileges
* - Public endpoints for organization listing
*
* @module OrganizationController
* @import {ExpressRequestAuthorized, ExpressResponse} from './../../types.js'
*/
// @ts-check
import './../../types.js';
import { UUID2hex, HEX2uuid } from '@commtool/sql-query';
import { errorLoggerUpdate, errorLoggerRead } from '../../utils/requestLogger.js';
import * as orgaService from './service.js';
/**
* Initialize a new organization with complete setup
*
* This endpoint creates a new organization with all required components:
* organization record, system user, super admin, visibility filters, and
* proper multi-tenant isolation. It's the primary endpoint for setting up
* new tenant environments.
*
* @param {Object} req - Express request object
* @param {Object} req.body - Organization initialization data
* @param {string} req.body.UID - Organization UUID
* @param {string} req.body.gender - Organization type (C=Combin)
* @param {Object} req.query - Query parameters
* @param {number} [req.query.timestamp] - Optional timestamp for backdating
* @param {Object} req.session - Session data
* @param {string} req.session.root - Root organization for context
* @param {Object} res - Express response object
*
* HTTP Status Codes:
* - 200: Organization created successfully
* - 300: Organization creation failed (business logic error)
* - 500: Internal server error
*
* Response format:
* - success: true/false
* - result: Organization data (on success)
* - message: Error description (on failure)
*
* Authentication: Requires admin privileges (checkAdmin middleware)
* Logging: Uses errorLoggerUpdate for error tracking
*/
export const initializeOrganization = async ( req, res) => {
try {
// Delegate to service layer for complete organization initialization
const result = await orgaService.initOrga(req);
if (result.success)
res.json(result);
else
// Status 300 indicates business logic failure, not server error
res.status(300).json(result);
} catch (e) {
// Log unexpected errors and return generic error response
errorLoggerUpdate(e);
res.status(500).json({ success: false, message: 'Internal server error' });
}
};
/**
* Get super admin user for a specific organization
*
* Retrieves the system user (super admin) that was created for the organization
* during initialization. This user is essential for automated operations,
* system tasks, and API integrations within the organization's context.
*
* @param {Object} req - Express request object
* @param {Object} req.params - URL parameters
* @param {string} req.params.orga - Organization UUID to get super admin for
* @param {Object} res - Express response object
*
* HTTP Status Codes:
* - 200: Super admin found and returned
* - 200: Super admin not found (success=false in response)
* - 500: Internal server error
*
* Response format (success):
* - success: true
* - result: Super admin UUID
*
* Response format (not found):
* - success: false
* - message: Descriptive error message with organization UID
*
* Authentication: Requires admin privileges (checkAdmin middleware)
* Logging: Uses errorLoggerRead for error tracking
*
* Use cases:
* - Bot system user identification
* - Automated operation setup
* - System integration configuration
* - Multi-tenant administration
*/
export const getSuperAdminForOrga = async (req, res) => {
const out = /** @type {ExpressResponse} */ (res);
try {
// Convert UUID to hex format and query for super admin
const sa = await orgaService.getSuperAdmin(req.params.orga);
if (sa)
out.json({ success: true, result: sa });
else
// Return success=false but 200 status for "not found" business case
out.json({ success: false, message: `superAdmin for the organisation ${req.params.orga} not found` });
} catch (e) {
// Log read errors and return generic error response
errorLoggerRead(e);
out.status(500).json({ success: false, message: 'Internal server error' });
}
};
/**
* Get organizations by specific UIDs (batch retrieval)
*
* Retrieves organization details for a provided list of organization UIDs.
* This endpoint is optimized for batch operations where you need information
* about multiple specific organizations rather than all organizations.
*
* @param {Object} req - Express request object
* @param {Object} req.body - Request body containing organization UIDs
* @param {string[]} req.body - Array of organization UUIDs to retrieve
* @param {Object} res - Express response object
*
* Request body example:
* [
* "123e4567-e89b-12d3-a456-426614174000",
* "987fcdeb-51a2-43d7-8f9e-123456789abc"
* ]
*
* HTTP Status Codes:
* - 200: Organizations retrieved successfully (even if some not found)
* - 500: Internal server error
*
* Response format:
* - success: true (always for successful requests)
* - result: Array of organization objects
* - UID: Organization UUID
* - Title: Organization title
* - Display: Formatted display name
*
* Authentication: No authentication required (public endpoint)
* Logging: Uses errorLoggerUpdate for error tracking
*
* Performance: Uses optimized IN clause for efficient batch retrieval
*
* Use cases:
* - Multi-organization dashboards
* - Batch organization validation
* - Cross-organization reporting
* - API integrations requiring specific org data
*/
export const getOrganizationsByUIDs = async (req, res) => {
try {
// Delegate to service layer for batch organization retrieval
const result = await orgaService.getOrganizationsByUIDs(req.body);
res.json({ success: true, result: result });
} catch (e) {
// Log update errors (POST endpoint) and return generic error response
errorLoggerUpdate(e);
res.status(500).json({ success: false, message: 'Internal server error' });
}
};
/**
* Get all organizations in the system
*
* Retrieves a complete list of all properly initialized organizations.
* This endpoint returns only organizations that have the required
* self-referencing memberSys links, ensuring data quality and consistency.
*
* @param {Object} req - Express request object (no parameters required)
* @param {Object} res - Express response object
*
* HTTP Status Codes:
* - 200: All organizations retrieved successfully
* - 500: Internal server error
*
* Response format:
* - success: true (always for successful requests)
* - result: Array of all organization objects
* - UID: Organization UUID
* - Title: Organization title from ObjectBase
* - Display: Formatted display name from Member table
*
* Authentication: No authentication required (public endpoint)
* Logging: Uses errorLoggerRead for error tracking
*
* Data quality: Only returns organizations with proper initialization
* (self-referencing memberSys links validate complete setup)
*
* Use cases:
* - System administration dashboards
* - Organization selection interfaces
* - Multi-tenant reporting
* - System health monitoring
* - Public organization directories
*/
export const getAllOrganizations = async (req, res) => {
try {
// Delegate to service layer for complete organization listing
const result = await orgaService.getAllOrganizations();
res.json({ success: true, result: result });
} catch (e) {
// Log read errors and return generic error response
errorLoggerRead(e);
res.status(500).json({ success: false, message: 'Internal server error' });
}
};
/**
* Update organization data with comprehensive property management
*
* This endpoint provides advanced organization data management with support
* for adding, updating, and removing properties. It handles null values as
* deletion indicators and provides detailed change tracking.
*
* @param {Object} req - Express request object
* @param {Object} req.params - URL parameters
* @param {string} req.params.orgaUID - Organization UUID to update
* @param {Object} req.body - Data object with properties to update
* - Properties with null values will be removed
* - Properties with non-null values will be added/updated
* @param {Object} res - Express response object
*
* Request body examples:
*
* Add/update properties:
* {
* "feature_flags": {"advanced_ui": true},
* "settings": {"timezone": "UTC"},
* "custom_config": {"theme": "dark"}
* }
*
* Remove properties (null values):
* {
* "deprecated_setting": null,
* "old_config": null
* }
*
* Mixed operations:
* {
* "new_feature": true, // Add
* "existing_setting": "new", // Update
* "old_feature": null // Remove
* }
*
* HTTP Status Codes:
* - 200: Data updated successfully
* - 400: Invalid request (missing UID or empty body)
* - 404: Organization not found
* - 500: Internal server error
*
* Response format (success):
* - success: true
* - message: Success confirmation
* - data: Complete organization data after update
* - changes: Detailed change breakdown
* - added: Array of newly created properties
* - updated: Array of modified properties
* - removed: Array of deleted properties
*
* Response format (error):
* - success: false
* - message: Error description
* - error: Detailed error message (development)
*
* Authentication: Requires employee privileges (checkEmployee middleware)
* Logging: Uses requestUpdateLogger and errorLoggerUpdate
*
* Use cases:
* - Feature flag management
* - Organization configuration updates
* - Custom settings management
* - Data cleanup operations
* - Bulk property management
*/
export const updateOrganizationData = async (req, res) => {
try {
// Validate required organization UID parameter
if (!req.params.orgaUID) {
return res.status(400).json({
success: false,
message: 'Organization UID is required'
});
}
// Validate non-empty request body
if (!req.body || Object.keys(req.body).length === 0) {
return res.status(400).json({
success: false,
message: 'Request body cannot be empty'
});
}
// Delegate to service layer for data update operation
const result = await orgaService.updateOrganizationData(req.params.orgaUID, req.body);
if (result.success) {
// Return successful update with complete change details
res.json(result);
} else {
// Return error with appropriate status code (404, 500, etc.)
res.status(result.status || 500).json({
success: false,
message: result.message || 'Failed to update organization data'
});
}
} catch (e) {
// Log unexpected errors and return generic error response
errorLoggerUpdate(e);
res.status(500).json({
success: false,
message: 'Internal server error',
error: e.message
});
}
};
/**
* Update organization login UID association
*
* This endpoint updates the login UID association for a specific organization.
* It allows changing which login system UID is linked from the login system (e.g. keycloak) for the organization.
*
* @param {Object} req - Express request object
* @param {Object} req.params - URL parameters
* @param {string} req.params.orgaUID - Organization UUID to update login for
* @param {Object} req.body - Data object with new login UID
* @param {string} req.body.UIDlogin - New login system UID to associate
* @param {Object} res - Express response object
*
* HTTP Status Codes:
* - 200: Login UID updated successfully
* - 400: Invalid request (missing UID)
* - 404: Organization not found
* - 500: Internal server error
*
* Response format (success):
* - success: true
* - message: Success confirmation
* - result: Updated organization data
*
* Response format (error):
* - success: false
* - message: Error description
* - error: Detailed error message (development)
* Authentication: Requires employee privileges (checkEmployee middleware)
* Logging: Uses requestUpdateLogger and errorLoggerUpdate
*
* Use cases:
* - Changing login associations for organizations
* - Updating authentication system links
* - Managing multi-tenant login configurations
*/
export const updateOrganizationLogin = async (req, res) => {
try {
// Validate required organization UID parameter
if (!req.params.orgaUID) {
return res.status(400).json({
success: false,
message: 'Organization UID is required'
});
}
// Validate required loginUID in request body
if (!req.body || !req.body.UIDlogin) {
return res.status(400).json({
success: false,
message: 'UIDlogin is required in request body'
});
}
// Delegate to service layer for login UID update operation
const result = await orgaService.updateOrganizationLogin(req.params.orgaUID, req.body.UIDlogin);
if (result.success) {
// Return successful update
res.json(result);
} else {
// Return error with appropriate status code (404, 500, etc.)
res.status(result.status || 500).json({
success: false,
message: result.message || 'Failed to update organization login UID'
});
}
} catch (e) {
// Log unexpected errors and return generic error response
errorLoggerUpdate(e);
res.status(500).json({
success: false,
message: 'Internal server error',
error: e.message
});
}
};