All files / src/middleware firebase.ts

70.88% Statements 56/79
75% Branches 3/4
66.66% Functions 2/3
70.88% Lines 56/79

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 811x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x     1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                              
import { AppCheckData, CallableRequest } from "firebase-functions/lib/common/providers/https";
import { HttpsError } from "firebase-functions/v2/https";
import { AuthData } from "firebase-functions/v2/tasks";
import { Message } from "../interfaces";
 
 
 
/**
 * Middleware function to verify if the request is from an App Check verified app.
 * If the app data is missing or invalid, an HttpsError is thrown.
 *
 * @param {AppCheckData | undefined} app - The App Check data of the incoming request, can be `undefined` if not available.
 * @param {Function} next - The callback function to pass control to the next middleware if the app is verified.
 * @throws {HttpsError} Throws an HttpsError if the app is not verified.
 */
export const isConfirmedApp = (app: AppCheckData | undefined, next: Function) => {
  if (app === undefined) {
    throw new HttpsError(
      "failed-precondition",
      "The function must be called from an App Check verified app."
    );
  }
  next(); // Continue to the next middleware
};
 
 
/**
 * Middleware function to check if the user is authorized.
 * If the auth data is missing or invalid, an HttpsError is thrown.
 *
 * @param {AuthData | undefined} auth - The authentication data of the user, can be `undefined` if not available.
 * @param {Function} next - The callback function to pass control to the next middleware if the user is authorized.
 * @throws {HttpsError} Throws an HttpsError if the user is not authorized.
 */
export const isAuthorizedUser = (auth: AuthData | undefined, next: Function) => {
  if (auth === undefined) {
    throw new HttpsError(
      "failed-precondition",
      "The function must be called by an authorized user"
    );
  }
  next(); // Continue to the next middleware
};
 
 
/**
 * Chains multiple middleware functions and executes them in sequence. 
 * Once all middlewares are executed, the final handler function is invoked.
 * If any middleware throws an error, the process is halted.
 *
 * @param {Function[]} middlewares - An array of middleware functions to be executed in order. 
 *                                    Each middleware should call the `next` function to proceed to the next middleware.
 * @param {CallableRequest<any>} request - The Firebase function's request object that contains the request data.
 * @param {Function} handler - The final function to be called after all middlewares are executed.
 * @returns {Promise<Message>} A promise that resolves with the result from the handler function once all middlewares have been processed.
 * @throws {Error} Throws an error if any middleware or the handler throws an exception.
 */
export const chainMiddlewares = async (
  middlewares: Function[],
  request: CallableRequest<any>,
  handler: Function
): Promise<Message> => {
  const execute = async (index: number): Promise<any> => {
    if (index < middlewares.length) {
      return new Promise((resolve, reject) => {
        try {
          middlewares[index](request, async () => {
            resolve(await execute(index + 1));
          });
        } catch (error) {
          reject(error);
        }
      });
    } else {
      return await handler(request); // Return the result from the handler
    }
  };
  return await execute(0); // Start the middleware chain
};