Example: Reading a User's Apps and Authorizations

The sample code below displays a user's team and Personal Account apps and authorizations.

📘

Primarily REST Platform API

This example primarily uses the REST Platform API, though it uses the GraphQL Platform API for a few functions. This example is approximately 50 percent slower than the primarily GraphQL Platform API example.

This code uses a combination of the GraphQL and REST Platform APIs. Because it used on-behalf-of functionality of the REST Platform API, you must configure the config.json object with a X-RapidAPI-Key from a team that has enterprise access to the platform API.

You can specify any Hub user's email address in the config.json object and read their apps and authorizations. Those users need no special access to the platform API.

Place the getAppsForAnyUser.js in the same directory as config.json.

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

let optionsCommonRest;
let optionsCommonGql;

let resultsLog = []; //used to log messages and a subset of the data obtained

// set specific user email address, Hub urls, key, category and preferences in config.json
let config = require("./config.json");

optionsCommonRest = {
  headers: {
    "x-rapidapi-host": config.rapidapi_host_rest,
    "x-rapidapi-key": config.key,
  },
};

optionsCommonGql = {
  method: "POST",
  url: config.base_url_gql,
  headers: {
    "x-rapidapi-host": config.rapidapi_host_gql,
    "x-rapidapi-key": config.key,
    "content-type": "application/json",
  },
};

runAll();

async function runAll() {
  console.log("working...");
  console.time("execution time");
  let results = {};

  results = await getUserByEmail(results);
  if (results.aUser[0]) {
    results = await getUserTeamIds(results);
    results = await getUserTeamNames(results);

    results.personalApps = await getApps(results.aUser[0].id);
    results = await getAllPersonalAppDetails(results);
    results = await getKeysForAllPersonalApps(results);

    results = await getTeamApps(results);
    results = await getAllTeamAppDetails(results);
    results = await getKeysForAllTeamApps(results);
    logResults(results);
  } else {
    resultsLog.push(`User ${config.useremail} not found!`);
    displayResultsLog();
  }

  console.timeEnd("execution time");
  return;
}

async function getUserByEmail(resultObj = {}) {
  const optionsUnique = {
    method: "GET",
    url: `${config.base_url_rest}admin/users`,
    params: { email: config.useremail },
  };
  const options = { ...optionsCommonRest, ...optionsUnique };
  let response = await axios.request(options);
  let locResults = {};
  locResults.aUser = response.data;
  return (resultObj = { ...resultObj, ...locResults });
}

async function getUserTeamIds(resultObj = {}) {
  if (!resultObj.aUser[0].id) return;
  const optionsUnique = {
    method: "GET",
    url: `${config.base_url_rest}admin/users/${resultObj.aUser[0].id}/teams`,
    params: { email: config.useremail },
  };
  const options = { ...optionsCommonRest, ...optionsUnique };
  let response = await axios.request(options);
  let locResults = {};
  locResults.aUserTeams = [];
  response.data.forEach((teamId) => {
    locResults.aUserTeams.push({ teamId: teamId }); // create a new object for each team
  });
  return (resultObj = { ...resultObj, ...locResults });
}

async function getUserTeamNames(resultObj) {
  const promises = resultObj.aUserTeams.map((team) =>
    getTeamNameFromID(team.teamId, resultObj.aUser[0].id)
  );
  const teamNames = await Promise.all(promises);
  resultObj.aUserTeams.forEach((team, index) => {
    team.name = teamNames[index];
  });
  return resultObj;
}

async function getTeamNameFromID(teamId, userId) {
  let teamName;
  const optionsUnique = {
    data: {
      query: `query Team($id: ID!) {
        team(id: $id) {
            id
            slugifiedName
            name
            createdAt
            ProjectAcls {
              Project {
                id
                name
              }
            }
          }
      }`,
      variables: { id: teamId },
    },
  };
  const optionsCommonClone = JSON.parse(JSON.stringify(optionsCommonGql)); // deep clone
  let options = { ...optionsCommonClone, ...optionsUnique };
  options.headers["on-behalf-of"] = userId;
  options = await transformOptionsForOnBehalfOf(options, userId, "user");

  let response = await axios.request(options);
  return (
    response?.data?.data?.team?.name || "team name not found" + " for " + teamId
  );
}

async function getApps(entityID) {
  const optionsUnique = {
    method: "GET",
    url: `${config.base_url_rest}apps`,
  };
  const optionsCommonClone = JSON.parse(JSON.stringify(optionsCommonRest)); // deep clone
  const options = { ...optionsCommonClone, ...optionsUnique };
  options.headers["on-behalf-of"] = entityID;
  let response = await axios.request(options);
  return response.data;
}

async function getTeamApps(resultObj) {
  const promises = resultObj.aUserTeams.map((team) => {
    return getApps(team.teamId).then((apps) => {
      team.apps = apps;
    });
  });

  await Promise.all(promises);
  return resultObj;
}

async function getAllPersonalAppDetails(resultObj) {
  const promises = resultObj.personalApps.map((app) => {
    return getAppDetails(resultObj.aUser[0].id, app.projectId).then(
      (details) => {
        app.details = details;
        return app;
      }
    );
  });
  const apps = await Promise.all(promises);
  resultObj.personalApps = apps;
  return resultObj;
}

async function getAllTeamAppDetails(resultObj) {
  const appDetailsPromises = [];

  for (const team of resultObj.aUserTeams) {
    for (const app of team.apps) {
      const appDetailsPromise = getAppDetails(team.teamId, app.projectId).then(
        (details) => {
          app.details = details;
        }
      );
      appDetailsPromises.push(appDetailsPromise);
    }
  }

  await Promise.all(appDetailsPromises);

  return resultObj;
}

async function getAppDetails(entityID, projectID) {
  const optionsUnique = {
    method: "GET",
    url: `${config.base_url_rest}apps/${projectID}`,
  };
  const optionsCommonClone = JSON.parse(JSON.stringify(optionsCommonRest)); // deep clone
  const options = { ...optionsCommonClone, ...optionsUnique };
  options.headers["on-behalf-of"] = entityID;
  let response = await axios.request(options);
  return response.data;
}

async function getKeysForAllPersonalApps(resultObj) {
  const promises = resultObj.personalApps.map((app) =>
    getAppAuthorizations(app.projectId, resultObj.aUser[0].id).then(
      (authorizations) => {
        app.authorizations = authorizations;
        return app;
      }
    )
  );
  resultObj.personalApps = await Promise.all(promises);

  return resultObj;
}

async function getKeysForAllTeamApps(resultObj) {
  const promises = [];

  for (const team of resultObj.aUserTeams) {
    for (const app of team.apps) {
      const promise = getAppAuthorizations(
        app.projectId,
        resultObj.aUser[0].id
      ).then((authorizations) => {
        app.authorizations = authorizations;
      });
      promises.push(promise);
    }
  }

  await Promise.all(promises);
  return resultObj;
}

async function getAppKeys(entityID, projectID) {
  const optionsUnique = {
    method: "GET",
    url: `${config.base_url_rest}apps/${projectID}/keys`,
  };
  const optionsCommonClone = JSON.parse(JSON.stringify(optionsCommonRest)); // deep clone
  const options = { ...optionsCommonClone, ...optionsUnique };
  options.headers["on-behalf-of"] = entityID;
  let response = await axios.request(options);
  // return only active production keys
  const validKeys = [];
  response.data.environments.forEach((env) => {
    if (
      env.applicationEnvironmentName === "Production" &&
      env.status === "ACTIVE"
    )
      validKeys.push(env);
  });
  return validKeys;
}

async function getAppAuthorizations(projectId, userId) {
  const optionsUnique = {
    data: {
      query: `query ApplicationAuthorizations($projectId: ID!) {
      applicationAuthorizations(where: {projectId: $projectId}) {
      id
      key
      name
      authorizationType
      authorizationValues
      }
    }`,
      variables: { projectId: projectId },
    },
  };
  const optionsCommonClone = JSON.parse(JSON.stringify(optionsCommonGql)); // deep clone
  let options = { ...optionsCommonClone, ...optionsUnique };
  options.headers["on-behalf-of"] = userId;
  options = await transformOptionsForOnBehalfOf(options, userId, "user");

  let response = await axios.request(options);
  return response.data.data.applicationAuthorizations;
}

let userKeyCache = {};
async function getAPersonalKeyForUser(userId) {
  if (userKeyCache[userId]) {
    return userKeyCache[userId];
  }
  let personalApps = await getApps(userId);
  let keys = await getAppKeys(userId, personalApps[0].projectId);
  let key;
  keys.forEach((env) => {
    if (
      env.applicationEnvironmentName === "Production" &&
      env.status === "ACTIVE"
    )
      if (!key) {
        key = env.key; //return first valid key
        userKeyCache[userId] = key;
      }
  });
  return key || "no key found";
}

async function transformOptionsForOnBehalfOf(options, entityID, entityType) {
  let results = {};
  if (entityType === "user") {
    options.headers["x-rapidapi-identity-key"] = await getAPersonalKeyForUser(
      entityID
    );
  }
  return options;
}

function logResults(results) {
  resultsLog.push(
    `Userid for ${results.aUser[0].email} is ${results.aUser[0].id}`
  );
  resultsLog.push(``);
  resultsLog.push(
    `Number of apps for ${results.aUser[0].email} in Personal Account: ${results.personalApps.length}`
  );
  results.personalApps.forEach((app) => {
    resultsLog.push(`    ${app.projectId} ${app.details.name}`);
    resultsLog.push(`       Authorizations: ${app.authorizations.length}`);
    app.authorizations.forEach((auth) => {
      if (auth.authorizationType === "RAPIDAPI") {
        resultsLog.push(`         RAPIDKEY ${auth.name} ${auth.key}`);
      } else {
        resultsLog.push(
          `         AUTHORIZATION ${auth.name} ${auth.authorizationType} ${auth.authorizationValues}`
        );
      }
    });
  });

  resultsLog.push(``);

  resultsLog.push(
    `Teams for ${results.aUser[0].email}: ${results.aUserTeams.length}`
  );
  results.aUserTeams.forEach((team) => {
    resultsLog.push(`  Team: ${team.name} (${team.teamId})`);
    resultsLog.push(`    Apps for team: ${team.apps.length}`);
    team.apps.forEach((app) => {
      resultsLog.push(`       ${app.projectId} ${app.details.name}`);
      resultsLog.push(
        `       Authorizations for team: ${app.authorizations.length}`
      );
      app.authorizations.forEach((auth) => {
        if (auth.authorizationType === "RAPIDAPI") {
          resultsLog.push(`         RAPIDKEY ${auth.name} ${auth.key}`);
        } else {
          resultsLog.push(
            `         AUTHORIZATION ${auth.name} ${auth.authorizationType} ${auth.authorizationValues}`
          );
        }
      });
    });
  });

  displayResultsLog();
}

function displayResultsLog() {
  resultsLog.forEach((entry) => console.log(entry));
}
{
    "rapidapi_host_rest": "[HOST FROM REST SAMPLE CODE].rapidapi.com",
    "base_url_rest": "https://[URL FROM REST SAMPLE CODE].rapidapi.com/v1/",
    "rapidapi_host_gql": "[HOST FROM GQL SAMPLE CODE].rapidapi.com",
    "base_url_gql": "[URL FROM REST SAMPLE CODE].rapidapi.com/",
    "key": "[KEY FROM TEAM WITH ENTERPRISE PLATFORM API ACCESS]",
    "useremail": "[email protected]"
}