Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 45 additions & 9 deletions backend/config/database.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**

Check failure on line 1 in backend/config/database.js

View check run for this annotation

Codeac.io / Codeac Code Quality

Parsing error: No Babel config file detected for /tmp/commit-1514384-eslint/backend/config/database.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files.
* PostgreSQL Database Configuration with Encryption
* Handles database connection, pooling, and encrypted data operations
*/
Expand Down Expand Up @@ -55,7 +55,13 @@
});

/**
* Initialize database connection and create tables
* Initialize database connection and create necessary tables.
*
* This function establishes a connection to the database using the provided configuration,
* tests the connection by executing a simple query, and logs the connection details.
* If the connection is successful, it proceeds to create the required tables by calling
* the createTables function. In case of any errors during the process, it logs the error
* and rethrows it for further handling.
*/
export async function initializeDatabase() {
try {
Expand Down Expand Up @@ -84,7 +90,12 @@
}

/**
* Create database tables
* Create database tables and initialize the database schema.
*
* This function connects to the database, begins a transaction, and creates several tables including users, wheel_stages, user_progress, user_sessions, user_encrypted_data, analytics_events, and audit_logs. It also enables necessary extensions, creates indexes for performance, and sets up triggers for updating timestamps. Finally, it inserts default wheel stages if they do not already exist. If any error occurs, the transaction is rolled back.
*
* @returns {Promise<void>} A promise that resolves when the tables are created and initialized.
* @throws {Error} If there is an error during the database operations.
*/
async function createTables() {
const client = await pool.connect();
Expand Down Expand Up @@ -302,7 +313,12 @@
}

/**
* Insert default wheel stages
* Insert default wheel stages into the database if none exist.
*
* This asynchronous function connects to the database and checks if any wheel stages are already present.
* If no stages are found, it inserts a predefined set of default stages, each with attributes such as title,
* symbol, essence, meaning, action, chant, and order_index. The function also logs the insertion process
* and handles any potential errors during the database operations.
*/
async function insertDefaultWheelStages() {
const defaultStages = [
Expand Down Expand Up @@ -425,7 +441,14 @@
}

/**
* Execute a database query with error handling and logging
* Execute a database query with error handling and logging.
*
* This function connects to the database, executes the provided SQL query with optional parameters,
* and logs the duration and result of the query. In case of an error, it logs the error message and
* rethrows the error. The database client is released after the operation, ensuring proper resource management.
*
* @param {string} text - The SQL query to be executed.
* @param {Array} [params=[]] - The parameters for the SQL query.
*/
export async function query(text, params = []) {
const start = Date.now();
Expand Down Expand Up @@ -454,7 +477,15 @@
}

/**
* Execute a transaction
* Execute a transaction.
*
* This function establishes a connection to the database, begins a transaction,
* and executes the provided callback function with the database client. If the
* callback completes successfully, the transaction is committed; if an error
* occurs, the transaction is rolled back. Finally, the database client is released.
*
* @param {Function} callback - A function that takes the database client as an argument
* and performs operations within the transaction.
*/
export async function transaction(callback) {
const client = await pool.connect();
Expand All @@ -473,7 +504,7 @@
}

/**
* Store encrypted data for a user
* Store encrypted data for a user in the database.
*/
export async function storeEncryptedData(userId, dataType, data) {
const encryptedData = encryptField(data);
Expand All @@ -487,7 +518,7 @@
}

/**
* Retrieve encrypted data for a user
* Retrieve and decrypt encrypted data for a user.
*/
export async function getEncryptedData(userId, dataType) {
const result = await query(`
Expand All @@ -504,7 +535,7 @@
}

/**
* Close database connection
* Closes the database connection.
*/
export async function closeDatabase() {
try {
Expand All @@ -516,7 +547,12 @@
}

/**
* Health check
* Performs a health check on the database.
*
* This function executes a simple query to verify the database's availability.
* It checks if the result indicates a healthy state by comparing the returned value
* to 1. In case of an error during the query execution, it logs the error and
* returns false to indicate an unhealthy state.
*/
export async function healthCheck() {
try {
Expand Down
71 changes: 61 additions & 10 deletions backend/middleware/auth.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**

Check failure on line 1 in backend/middleware/auth.js

View check run for this annotation

Codeac.io / Codeac Code Quality

Parsing error: No Babel config file detected for /tmp/commit-1514384-eslint/backend/middleware/auth.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files.
* JWT Authentication Middleware
* Provides secure token-based authentication with refresh tokens
*/
Expand All @@ -16,7 +16,7 @@
const JWT_REFRESH_EXPIRY = process.env.JWT_REFRESH_EXPIRY || '7d';

/**
* Generate JWT access token
* Generates a JWT access token with the given payload.
*/
export function generateAccessToken(payload) {
return jwt.sign(
Expand All @@ -37,7 +37,7 @@
}

/**
* Generate JWT refresh token
* Generates a JWT refresh token.
*/
export function generateRefreshToken(payload) {
return jwt.sign(
Expand All @@ -58,7 +58,14 @@
}

/**
* Verify JWT token
* Verify JWT token.
*
* This function checks the validity of a JWT token using a specified secret based on whether it is a refresh token or not.
* It decodes the token and returns an object indicating its validity, the decoded payload, and whether it has expired.
* If an error occurs during verification, it handles different error types to provide specific feedback on the token's status.
*
* @param {string} token - The JWT token to verify.
* @param {boolean} [isRefresh=false] - Indicates if the token is a refresh token.
*/
export function verifyToken(token, isRefresh = false) {
try {
Expand Down Expand Up @@ -103,7 +110,17 @@
}

/**
* Authentication middleware
* Authentication middleware for validating user tokens.
*
* This middleware checks for a valid Bearer token in the authorization header, verifies its validity and type,
* and retrieves user information. It handles various authentication errors, including blacklisted tokens,
* expired tokens, and inactive accounts, responding with appropriate status codes and messages.
* If successful, it attaches user and token information to the request object for further processing.
*
* @param req - The request object containing the HTTP request data.
* @param res - The response object used to send HTTP responses.
* @param next - The next middleware function in the stack.
* @throws Error If an internal error occurs during authentication.
*/
export async function authMiddleware(req, res, next) {
try {
Expand Down Expand Up @@ -212,7 +229,9 @@
}

/**
* Optional authentication middleware (doesn't fail if no token)
* Optional authentication middleware that allows requests to proceed without a token.
*
* This middleware checks for the presence of an authorization header. If the header is missing or does not start with 'Bearer ', it sets req.user and req.token to null and calls next() to continue the request. If the header is present, it attempts to call the authMiddleware function. If authMiddleware throws an error, it catches the error, sets req.user and req.token to null, and continues the request.
*/
export async function optionalAuthMiddleware(req, res, next) {
const authHeader = req.headers.authorization;
Expand All @@ -234,7 +253,14 @@
}

/**
* Role-based authorization middleware
* Role-based authorization middleware.
*
* This middleware checks if the user is authenticated and has one of the required roles.
* If the user is not authenticated, a 401 status is returned with an appropriate message.
* If the user's role is not included in the specified roles, a 403 status is returned,
* indicating insufficient permissions. If both checks pass, the middleware calls the next function.
*
* @param {...string} roles - The roles that are required to access the resource.
*/
export function requireRole(...roles) {
return (req, res, next) => {
Expand All @@ -259,7 +285,16 @@
}

/**
* Refresh token middleware
* Middleware to refresh the token for authenticated users.
*
* This function checks for the presence of a refresh token in the request body, verifies its validity, and ensures it is not blacklisted.
* It also checks the token type and retrieves the associated user information, attaching it to the request object for further processing.
* If any validation fails, appropriate error responses are sent back to the client.
*
* @param req - The request object containing the refresh token in the body.
* @param res - The response object used to send responses back to the client.
* @param next - The next middleware function in the stack.
* @throws Error If an internal server error occurs during the token refresh process.
*/
export async function refreshTokenMiddleware(req, res, next) {
try {
Expand Down Expand Up @@ -334,7 +369,16 @@
}

/**
* Logout middleware - blacklist tokens
* Logout middleware - blacklist tokens.
*
* This middleware handles the logout process by blacklisting the access token and, if provided, the refresh token.
* It checks for the presence of the access token and blacklists it if available. If a refresh token is included in
* the request body, it verifies the token and blacklists it if valid. The function logs the logout action and
* proceeds to the next middleware, even if an error occurs during the blacklisting process.
*
* @param {Object} req - The request object containing user and token information.
* @param {Object} res - The response object.
* @param {Function} next - The next middleware function to call.
*/
export async function logoutMiddleware(req, res, next) {
try {
Expand Down Expand Up @@ -367,7 +411,7 @@
}

/**
* Generate token pair (access + refresh)
* Generates a token pair (access + refresh) from the given payload.
*/
export function generateTokenPair(payload) {
const accessToken = generateAccessToken(payload);
Expand All @@ -383,7 +427,14 @@
}

/**
* Extract token from request
* Extract token from request.
*
* This function retrieves a token from the provided request object. It first checks the
* authorization header for a Bearer token and returns it if present. If the header is
* not available or does not contain a Bearer token, it falls back to checking the query
* parameters for a token, specifically for WebSocket scenarios.
*
* @param {Object} req - The request object containing headers and query parameters.
*/
export function extractTokenFromRequest(req) {
const authHeader = req.headers.authorization;
Expand Down
Loading
Loading