src_OAuth.js

/**
 * @fileoverview This file contains OAuth functions for the application.
 * @author Sean McGinty <newfolderlocation@gmail.com>
 * @version 1.2.0
 * @license GPL-3.0
 */

const axios = require("axios").default;

/**
 * @description This function is used to authorize the application with TidyHQ and return an access token.
 * @param {string} client_id - The client ID of the application.
 * @param {string} redirect_uri - The redirect URI of the application.
 * @param {string} [host="https://accounts.tidyhq.com"] - The host url of TidyHQ.
 * @returns {Promise<string>} - The access token.
 * @throws {TypeError} If `client_id` or `redirect_uri` are not strings.
 * @throws {RangeError} If `client_id` is not 64 characters long or `redirect_uri` is not a valid URL.
 * @throws {Error} For any Axios-related errors, including network issues or invalid responses.
 */
async function authorize(client_id, redirect_uri, host = "https://accounts.tidyhq.com") {
    if (typeof client_id !== "string") throw new TypeError("OAuth.authorize: client_id must be a string.");
    if (typeof redirect_uri !== "string") throw new TypeError("OAuth.authorize: redirect_uri must be a string.");
    if (client_id.length !== 64) throw new RangeError("OAuth.authorize: client_id must be 64 characters long.");
    if (!redirect_uri.startsWith("http")) throw new RangeError("OAuth.authorize: redirect_uri must be a valid URL.");

    let code = "";
    await axios.get(`${host}/oauth/authorize?client_id=${client_id}&redirect_uri=${redirect_uri}&response_type=code`).then((response) => {
        code = response.data;
    }).catch((error) => {
        throw new Error(`OAuth.authorize: ${error}\n${error.response.data}`);
    });
    return code;
}

/**
 * @description This function is used to authorize using a username and password.
 * @param {string} client_id - The client ID of the application.
 * @param {string} client_secret - The client secret of the application.
 * @param {string} username - The username of the user.
 * @param {string} password - The password of the user.
 * @param {string} domain_prefix - The domain prefix of the club.
 * @returns {Promise<string>} - The access token.
 * @throws {TypeError} If `client_id`, `client_secret`, `username`, `password`, or `domain_prefix` are not strings.
 * @throws {RangeError} If `client_id` or `client_secret` are not 64 characters long.
 * @throws {Error} For any Axios-related errors, including network issues or invalid responses.
 */
async function authorizeWithPassword(client_id, client_secret, username, password, domain_prefix, host = "https://accounts.tidyhq.com") {
    if (typeof client_id !== "string") throw new TypeError("OAuth.authorizeWithPassword: client_id must be a string.");
    if (typeof client_secret !== "string") throw new TypeError("OAuth.authorizeWithPassword: client_secret must be a string.");
    if (typeof username !== "string") throw new TypeError("OAuth.authorizeWithPassword: username must be a string.");
    if (typeof password !== "string") throw new TypeError("OAuth.authorizeWithPassword: password must be a string.");
    if (client_id.length !== 64) throw new RangeError("OAuth.authorizeWithPassword: client_id must be 64 characters long.");
    if (client_secret.length !== 64) throw new RangeError("OAuth.authorizeWithPassword: client_secret must be 64 characters long.");

    let accessToken = "";
    await axios.post(`${host}/oauth/token`, {
        client_id: client_id,
        client_secret: client_secret,
        username: username,
        password: password,
        domain_prefix: domain_prefix,
        grant_type: "password",
    }).then((response) => {
        accessToken = response.data.access_token;
    }).catch((error) => {
        throw new Error(`OAuth.authorizeWithPassword: ${error}\n${error.response.data}`);
    });
    return accessToken;
}

/**
 * @description This function is used to request an access token from TidyHQ.
 * @param {string} client_id - The client ID of the application.
 * @param {string} client_secret - The client secret of the application.
 * @param {string} redirect_uri - The redirect URI of the application.
 * @param {string} code - The code returned from the authorize function.
 * @returns {Promise<string>} - The access token.
 * @throws {TypeError} If `client_id`, `client_secret`, `redirect_uri`, or `code` are not strings.
 * @throws {RangeError} If `client_id` or `client_secret` are not 64 characters long or `redirect_uri` is not a valid URL.
 * @throws {Error} For any Axios-related errors, including network issues or invalid responses.
 */
async function requestAccessToken(client_id, client_secret, redirect_uri, code, host = "https://accounts.tidyhq.com") {
    if (typeof client_id !== "string") throw new TypeError("OAuth.requestAccessToken: client_id must be a string.");
    if (typeof client_secret !== "string") throw new TypeError("OAuth.requestAccessToken: client_secret must be a string.");
    if (typeof redirect_uri !== "string") throw new TypeError("OAuth.requestAccessToken: redirect_uri must be a string.");
    if (typeof code !== "string") throw new TypeError("OAuth.requestAccessToken: code must be a string.");
    if (client_id.length !== 64) throw new RangeError("OAuth.requestAccessToken: client_id must be 64 characters long.");
    if (client_secret.length !== 64) throw new RangeError("OAuth.requestAccessToken: client_secret must be 64 characters long.");
    if (!redirect_uri.startsWith("http")) throw new RangeError("OAuth.requestAccessToken: redirect_uri must be a valid URL.");

    let accessToken = "";
    await axios.post(`${host}/oauth/token`, {
        client_id: client_id,
        client_secret: client_secret,
        redirect_uri: redirect_uri,
        code: code,
        grant_type: "authorization_code"
    }).then((response) => {
        accessToken = response.data.access_token;
    }).catch((error) => {
        throw new Error(`OAuth.requestAccessToken: ${error}\n${error.response.data}`);
    });
    return accessToken;
}

module.exports = { authorize, authorizeWithPassword, requestAccessToken };