Source: middleware/verifier.js

const query = require("../util/query.js");

/**
 * Middleware that verifies that the provided user is an admin of the provided choir
 * @param {*} req
 * @param {string} req.body.choirId The choir ID to be accessed. NOTE: Only need to pass choirId in body or query not both
 * @param {string} req.query.choirId The choir ID to be accessed. NOTE: Only need to pass choirId in body or query not both
 * @param {*} res 
 * @returns {boolean} True if the user is an admin of the choir matching the provided choirId false otherwise
 */
const verifyAdmin = async(req, res) => {
  let choirId = req.body.choirId;
  if (!choirId) {
    choirId = req.query.choirId;
  }
  if (choirId) {
    try {
      let obj_1 = await query("SELECT COUNT(*) FROM tma.member WHERE person_id=? AND choir_id=unhex(?) AND member_type = 'admin' AND member_status='verified'", [res.locals.uid, choirId]);
      return obj_1.results[0]['COUNT(*)'] !== 0;
    } catch(error) {
      return false;
    }
  } else {
    return false;
  }
}

/**
 * Middleware that verifies that the user is an admin of the provided member
 * @param {*} req 
 * @param {string} req.body.memberId The member ID to be accessed. NOTE: Only need to pass memberId in body or query not both
 * @param {string} req.query.memberId The member ID to be accessed. NOTE: Only need to pass memberId in body or query not both
 * @param {*} res 
 * @returns {string} Either the choir_id that the member is in if the user is an admin otherwise null
 */
const verifyAdminOfMember = async(req, res) => {
  let memberId = req.body.memberId;
  if (!memberId) {
    memberId = req.query.memberId;
  }
  if (memberId) {
    try {
      const obj_1 = await query("SELECT DISTINCT hex(choir_id) FROM tma.member WHERE person_id=? AND member_type = 'admin' AND member_status='verified'", [res.locals.uid]);
      if (obj_1.results_1.length === 0) {
          return null;
      } else {
        const obj_2 = await query("SELECT hex(choir_id) FROM tma.member WHERE member_id=unhex(?)", [memberId]);
        if (obj_2.results_2.length === 0) {
          return null;
        } else {
          let id_1 = obj_1.results_1[0]['hex(choir_id)'];
          let id_2 = obj_2.results_2[0]['hex(choir_id)'];
          if ((Array.isArray(id_1) && id_1.includes(id_2)) || id_1 === id_2) {
            return id_2;
          } else {
            return null;
          }
        }
      }
    } catch(error) {
      return null;
    }
  } else {
    return null;
  }
}

/**
 * Middleware that verifies that the user is verified in the given choir
 * @param {*} req 
 * @param {string} req.body.choirId The choir ID to be accessed. NOTE: Only need to pass choirId in body or query not both
 * @param {string} req.query.choirId The choir ID to be accessed. NOTE: Only need to pass choirId in body or query not both
 * @param {*} res 
 * @returns {boolean} Whether the user is verified in the given choir
 */
const verifyUserIsVerified = async(req,res) => {
  let choirId = req.body.choirId;
  if (!choirId) {
    choirId = req.query.choirId;
  }
  if (choirId) {
    try {
      const obj_1 = await query("SELECT COUNT(*) FROM tma.member WHERE person_id=? AND choir_id=unhex(?) AND member_status='verified'", [res.locals.uid, choirId]);
      return obj_1.results[0]['COUNT(*)'] !== 0
    } catch(error) {
      return false;
    }
  } else {
    return false;
  }
}

/**
 * Middleware that verifies that the user is a member of the provided piece of sheet music and that they are verified
 * @param {*} req 
 * @param {string} req.body.sheetMusicId The sheet music ID to be accessed. NOTE: Only need to pass sheetMusicId in body or query not both
 * @param {string} req.query.sheetMusicId The sheet music ID to be accessed. NOTE: Only need to pass sheetMusicId in body or query not both
 * @param {*} res 
 * @returns {string} Either the choir_id if the user is a member otherwise null
 */
const verifyMemberOfSheetMusic = async(req,res) => {
  let sheetMusicId = req.body.sheetMusicId;

  if (!sheetMusicId) {
    sheetMusicId = req.query.sheetMusicId;
  }
  if (sheetMusicId) {
    try {
      const obj_1 = await query("SELECT DISTINCT hex(choir_id) FROM tma.member WHERE person_id=? AND member_status='verified'", [res.locals.uid]);
      if (obj_1.results.length === 0) {
        return null;
      } else {
        const obj_2 = await query("SELECT hex(choir_id) FROM tma.sheet_music WHERE sheet_music_id=unhex(?)", [sheetMusicId]);
        if (obj_2.results.length === 0) {
          return null;
        } else {
          let id_1 = obj_1.results[0]['hex(choir_id)'];
          let id_2 = obj_2.results[0]['hex(choir_id)'];
          if ((Array.isArray(id_1) && id_1.includes(id_2)) || id_1 === id_2) {
            return id_2;
          } else {
            return null;
          }
        }
      }
    } catch(error) {
      return null;
    }
  } else {
    return null;
  }
}

/**
 * Middleware that verifies that the user's person_id matches the person_id of the member with the provided member's id
 * @param {*} req
 * @param {string} req.body.memberId The member ID to be accessed. NOTE: Only need to pass memberId in body or query not both
 * @param {string} req.query.memberId The member ID to be accessed. NOTE: Only need to pass memberId in body or query not both
 * @param {*} res
 * @returns {boolean} True if the user's person_id matches false otherwise
 */
const verifyUserIsMember = async(req, res) => {
  let memberId = req.body.memberId;
  if (!memberId) {
    memberId = req.query.memberId;
  }
  if (memberId) {
    try {
      const obj_1 = await query("SELECT COUNT(*) FROM tma.member WHERE member_id=unhex(?) AND person_id=?", [memberId, res.locals.uid]);
      return obj_1.results[0]["COUNT(*)"] > 0;
    } catch(error) {
      return false;
    }
  } else {
    return false;
  }
}

module.exports = {admin: verifyAdmin, adminOfMember: verifyAdminOfMember, userIsVerified : verifyUserIsVerified, memberOfSheetMusic: verifyMemberOfSheetMusic, userIsMember: verifyUserIsMember};