diff --git a/.env.example b/.env.example index cba7ab8..a749ff8 100644 --- a/.env.example +++ b/.env.example @@ -1,19 +1,32 @@ -# Required for Administration API tutorial, to acquire auth tokens -# See https://docs.camunda.io/docs/apis-tools/administration-api/authentication/#client-credentials-and-scopes +# Shared by various API tutorials +CLUSTER_ID=fill-this-in + +------------------------------------ + +# Administration API tutorial + +## Capture these values from an API client created at the organization level, with access to the Cluster scope. +## See https://docs.camunda.io/docs/apis-tools/administration-api/authentication/#client-credentials-and-scopes for more details. +### This value comes from the `CAMUNDA_CONSOLE_CLIENT_ID`. ADMINISTRATION_CLIENT_ID=fill-this-in +### This value comes from the `CAMUNDA_CONSOLE_CLIENT_SECRET`. ADMINISTRATION_CLIENT_SECRET=fill-this-in -# Required for Administration API tutorial, to access API -ADMINISTRATION_API_URL=https://api.cloud.camunda.io +## These values will only change if you're not using SaaS. ADMINISTRATION_AUDIENCE=api.cloud.camunda.io -CLUSTER_ID=fill-this-in +ADMINISTRATION_API_URL=https://api.cloud.camunda.io ------------------------------------ -# Required for non-Administration API tutorials, to acquire auth tokens -COMPONENTS_CLIENT_ID=fill-this-in -COMPONENTS_CLIENT_SECRET=fill-this-in +# Optimize API tutorial -# Required for Optimize API tutorial, to access API +## Capture these values from an API client created at the cluster level, with access to the Optimize scope. +### This value comes from the `ZEEBE_CLIENT_ID`. +OPTIMIZE_CLIENT_ID=fill-this-in +### This value comes from the `ZEEBE_CLIENT_SECRET`. +OPTIMIZE_CLIENT_SECRET=fill-this-in +### This value comes from the `CAMUNDA_OPTIMIZE_BASE_URL`. OPTIMIZE_BASE_URL=fill-this-in + +## This value will only change if you're not using SaaS. OPTIMIZE_AUDIENCE=optimize.camunda.io \ No newline at end of file diff --git a/auth.js b/auth.js index e3f782d..f92887e 100644 --- a/auth.js +++ b/auth.js @@ -1,28 +1,40 @@ import { AuthorizationCode } from "simple-oauth2"; -const adminConfiguration = { - // These credentials come from your .env file. - clientID: process.env.ADMINISTRATION_CLIENT_ID, - clientSecret: process.env.ADMINISTRATION_CLIENT_SECRET -}; +// This function can be used by callers to retrieve a token prior to their API calls. +/** + * @param {Object} config - A configuration object for authorizing the API client. + * @param {string} config.clientId - The client ID for the API client. + * @param {string} config.clientSecret - The client secret for the API client. + * @param {string} config.audience - The audience associated with the target API. + * @returns {string} + */ +export async function getAccessToken(config) { + try { + const client = configureAuthorizationClient(config); + const tokenParams = getTokenParams(config); -const componentConfiguration = { - // These credentials come from your .env file. - clientID: process.env.COMPONENTS_CLIENT_ID, - clientSecret: process.env.COMPONENTS_CLIENT_SECRET -}; + const result = await client.getToken(tokenParams); + const accessToken = client.createToken(result); -// Configure our authorization request. -function configureAuthorizationClient(targetApi) { - const configSource = - targetApi === "administration" - ? adminConfiguration - : componentConfiguration; + // Return the actual token that can be passed as an Authorization header in each request. + return accessToken.token.token.access_token; + } catch (error) { + throw new Error(error.message); + } +} +// Configure our authorization request. +/** + * @param {Object} config - A configuration object for authorizing the API client. + * @param {string} config.clientId - The client ID for the API client. + * @param {string} config.clientSecret - The client secret for the API client. + * @returns {Object} A configured authorization client. + */ +function configureAuthorizationClient({ clientId, clientSecret }) { const config = { client: { - id: configSource.clientID, - secret: configSource.clientSecret + id: clientId, + secret: clientSecret }, auth: { // This is the URL for our auth server. @@ -36,37 +48,14 @@ function configureAuthorizationClient(targetApi) { } // Define additional parameters for the authorization request. -function getTokenParams(audience) { +/** + * @param {Object} config - A configuration object for authorizing the API client. + * @param {string} config.audience - The audience associated with the target API. + * @returns {Object} Token parameters for the authorization request. + */ +function getTokenParams({ audience }) { return { // This audience is specific to the Camunda API we are calling. audience }; } - -// This function can be used by callers to retrieve a token prior to their API calls. -/** - * - * @param {"administration" | "components"} targetApi Use "administration" for only the administration API; "components" for all other component APIs. - * @param {string} audience The `audience` required by the target API. - * @returns - */ -export async function getAccessToken(targetApi, audience) { - if (targetApi !== "administration" && targetApi !== "components") { - throw new Error( - "Unexpected targetApi value. Expecing 'administration' or 'components'." - ); - } - - try { - const client = configureAuthorizationClient(targetApi); - const tokenParams = getTokenParams(audience); - - const result = await client.getToken(tokenParams); - const accessToken = client.createToken(result); - - // Return the actual token that can be passed as an Authorization header in each request. - return accessToken.token.token.access_token; - } catch (error) { - throw new Error(error.message); - } -} diff --git a/completed/administration.js b/completed/administration.js index eb2b80e..84d11de 100644 --- a/completed/administration.js +++ b/completed/administration.js @@ -1,15 +1,16 @@ import axios from "axios"; import { getAccessToken } from "./auth.js"; +const authorizationConfiguration = { + clientId: process.env.ADMINISTRATION_CLIENT_ID, + clientSecret: process.env.ADMINISTRATION_CLIENT_SECRET, + audience: process.env.ADMINISTRATION_AUDIENCE +}; + // An action that lists all clients. async function listClients() { - const administrationAudience = process.env.ADMINISTRATION_AUDIENCE; - // Every request needs an access token. - const accessToken = await getAccessToken( - "administration", - administrationAudience - ); + const accessToken = await getAccessToken(authorizationConfiguration); // These settings come from your .env file. const administrationApiUrl = process.env.ADMINISTRATION_API_URL; @@ -45,13 +46,8 @@ async function listClients() { // An action that adds a new client. async function addClient([clientName]) { - const administrationAudience = process.env.ADMINISTRATION_AUDIENCE; - // Every request needs an access token. - const accessToken = await getAccessToken( - "administration", - administrationAudience - ); + const accessToken = await getAccessToken(authorizationConfiguration); // These settings come from your .env file. const administrationApiUrl = process.env.ADMINISTRATION_API_URL; @@ -95,13 +91,8 @@ async function addClient([clientName]) { // An action that views one client. async function viewClient([clientId]) { - const administrationAudience = process.env.ADMINISTRATION_AUDIENCE; - // Every request needs an access token. - const accessToken = await getAccessToken( - "administration", - administrationAudience - ); + const accessToken = await getAccessToken(authorizationConfiguration); // These settings come from your .env file. const administrationApiUrl = process.env.ADMINISTRATION_API_URL; @@ -136,13 +127,8 @@ async function viewClient([clientId]) { // An action that deletes a client. async function deleteClient([clientId]) { - const administrationAudience = process.env.ADMINISTRATION_AUDIENCE; - // Every request needs an access token. - const accessToken = await getAccessToken( - "administration", - administrationAudience - ); + const accessToken = await getAccessToken(authorizationConfiguration); // These settings come from your .env file. const administrationApiUrl = process.env.ADMINISTRATION_API_URL; diff --git a/completed/optimize.js b/completed/optimize.js index fe8bc7e..6976d96 100644 --- a/completed/optimize.js +++ b/completed/optimize.js @@ -1,9 +1,14 @@ import axios from "axios"; import { getAccessToken } from "./auth.js"; +const authorizationConfiguration = { + clientId: process.env.OPTIMIZE_CLIENT_ID, + clientSecret: process.env.OPTIMIZE_CLIENT_SECRET, + audience: process.env.OPTIMIZE_AUDIENCE +}; + async function listDashboards([collectionId]) { - const optimizeAudience = process.env.OPTIMIZE_AUDIENCE; - const accessToken = await getAccessToken("components", optimizeAudience); + const accessToken = await getAccessToken(authorizationConfiguration); const optimizeApiUrl = process.env.OPTIMIZE_BASE_URL; // This is the API endpoint to list your existing dashboard IDs @@ -33,11 +38,10 @@ async function listDashboards([collectionId]) { async function deleteDashboard([dashboardId]) { console.log(`deleting dashboard ${dashboardId}`); - const optimizeAudience = process.env.OPTIMIZE_AUDIENCE; - const accessToken = await getAccessToken("components", optimizeAudience); - const optimizeApiUrl = process.env.OPTIMIZE_API_URL; + const accessToken = await getAccessToken(authorizationConfiguration); - const url = `${optimizeApiUrl}/public/dashboard/${dashboardId}`; + const optimizeApiUrl = process.env.OPTIMIZE_BASE_URL; + const url = `${optimizeApiUrl}/api/public/dashboard/${dashboardId}`; // Configure the API call. const options = { @@ -55,7 +59,7 @@ async function deleteDashboard([dashboardId]) { // Process the results from the API call. if (response.status === 204) { - console.log(`Dashboard ${clientId} was deleted!`); + console.log(`Dashboard ${dashboardId} was deleted!`); } else { // Emit an unexpected error message. console.error("Unable to delete dashboard!");