Skip to content

Commit 8d5e7e8

Browse files
authored
feat(arcgis-rest-developer-credentials)!: support updated API keys
* feat(arcgis-rest-developer-credentials)!: support updated API keys * chore: remove demo * chore: update package lock * chore: update package lock
1 parent b013b07 commit 8d5e7e8

25 files changed

+692
-1415
lines changed

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/arcgis-rest-developer-credentials/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@esri/arcgis-rest-developer-credentials",
3-
"version": "1.1.0",
3+
"version": "2.0.0",
44
"description": "Developer Credentials for @esri/arcgis-rest-js",
55
"license": "Apache-2.0",
66
"keywords": [

packages/arcgis-rest-developer-credentials/src/createApiKey.ts

+62-16
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
ICreateItemOptions,
66
createItem,
77
getItem,
8-
IItemAdd
8+
IItemAdd,
9+
updateItem
910
} from "@esri/arcgis-rest-portal";
1011
import {
1112
IApiKeyResponse,
@@ -18,8 +19,11 @@ import {
1819
appToApiKeyProperties,
1920
filterKeys,
2021
extractBaseRequestOptions,
21-
arePrivilegesValid
22+
generateApiKeyTokens,
23+
generateOptionsToSlots,
24+
buildExpirationDateParams
2225
} from "./shared/helpers.js";
26+
import { getRegisteredAppInfo } from "./shared/getRegisteredAppInfo.js";
2327

2428
/**
2529
* Used to register an API key. See the [security and authentication](https://developers.arcgis.com/documentation/mapping-apis-and-services/security/api-keys/) for more information about API key.
@@ -37,7 +41,7 @@ import {
3741
* title: "xyz_title",
3842
* description: "xyz_desc",
3943
* tags: ["xyz_tag1", "xyz_tag2"],
40-
* privileges: [Privileges.Geocode, Privileges.FeatureReport],
44+
* privileges: ["premium:user:networkanalysis:routing"],
4145
* authentication: authSession
4246
* }).then((registeredAPIKey: IApiKeyResponse) => {
4347
* // => {apiKey: "xyz_key", item: {tags: ["xyz_tag1", "xyz_tag2"], ...}, ...}
@@ -52,14 +56,9 @@ import {
5256
export async function createApiKey(
5357
requestOptions: ICreateApiKeyOptions
5458
): Promise<IApiKeyResponse> {
55-
if (!arePrivilegesValid(requestOptions.privileges)) {
56-
throw new Error("The `privileges` option contains invalid privileges.");
57-
}
58-
5959
requestOptions.httpMethod = "POST";
6060

6161
// filter param buckets:
62-
6362
const baseRequestOptions = extractBaseRequestOptions(requestOptions); // snapshot of basic IRequestOptions before customized params being built into it
6463

6564
const itemAddProperties: Array<keyof IItemAdd> = [
@@ -79,11 +78,13 @@ export async function createApiKey(
7978
"url"
8079
];
8180

82-
// step 1: add item
81+
/**
82+
* step 1: create item
83+
*/
8384
const createItemOption: ICreateItemOptions = {
8485
item: {
8586
...filterKeys(requestOptions as any, itemAddProperties),
86-
type: "API Key"
87+
type: "Application"
8788
},
8889
...baseRequestOptions,
8990
authentication: requestOptions.authentication,
@@ -94,26 +95,71 @@ export async function createApiKey(
9495

9596
const createItemResponse = await createItem(createItemOption);
9697

97-
// step 2: register app
98-
const registerAppOption: IRegisterAppOptions = {
98+
/**
99+
* getRegisteredAppInfoRoute
100+
*/
101+
const registerAppOptions: IRegisterAppOptions = {
99102
itemId: createItemResponse.id,
100-
appType: "apikey",
101-
redirect_uris: [],
103+
appType: "multiple",
104+
redirect_uris: ["urn:ietf:wg:oauth:2.0:oob"],
102105
httpReferrers: requestOptions.httpReferrers || [],
103106
privileges: requestOptions.privileges,
104107
...baseRequestOptions,
105108
authentication: requestOptions.authentication
106109
};
107110

108-
const registeredAppResponse = await registerApp(registerAppOption);
111+
const registeredAppResponse = await registerApp(registerAppOptions);
112+
113+
/**
114+
* step 3: update item with desired expiration dates
115+
* you cannot set the expiration date propierties until you
116+
* regiester the app so this has to be a seperate step
117+
*/
118+
await updateItem({
119+
...baseRequestOptions,
120+
item: {
121+
id: createItemResponse.id,
122+
...buildExpirationDateParams(requestOptions, true)
123+
},
124+
authentication: requestOptions.authentication
125+
});
126+
127+
/*
128+
* step 4: get item info
129+
*/
109130
const itemInfo = await getItem(registeredAppResponse.itemId, {
110131
...baseRequestOptions,
111132
authentication: requestOptions.authentication,
112133
params: { f: "json" }
113134
});
114135

136+
/**
137+
* step 5: generate tokens if requested
138+
*/
139+
const generatedTokens = await generateApiKeyTokens(
140+
itemInfo.id,
141+
generateOptionsToSlots(
142+
requestOptions.generateToken1,
143+
requestOptions.generateToken2
144+
),
145+
{
146+
...baseRequestOptions,
147+
authentication: requestOptions.authentication
148+
}
149+
);
150+
151+
/**
152+
* step 6: get registered app info to get updated active key status
153+
*/
154+
const updatedRegisteredAppResponse = await getRegisteredAppInfo({
155+
...baseRequestOptions,
156+
itemId: itemInfo.id,
157+
authentication: requestOptions.authentication
158+
});
159+
115160
return {
116-
...appToApiKeyProperties(registeredAppResponse),
161+
...generatedTokens,
162+
...appToApiKeyProperties(updatedRegisteredAppResponse),
117163
item: itemInfo
118164
};
119165
}

packages/arcgis-rest-developer-credentials/src/deleteApiKey.ts

-60
This file was deleted.

packages/arcgis-rest-developer-credentials/src/deleteOAuthApp.ts

-60
This file was deleted.

packages/arcgis-rest-developer-credentials/src/index.ts

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
export * from "./createApiKey.js";
55
export * from "./updateApiKey.js";
66
export * from "./getApiKey.js";
7-
export * from "./deleteApiKey.js";
8-
export * from "./deleteOAuthApp.js";
97
export * from "./getOAuthApp.js";
108
export * from "./updateOAuthApp.js";
119
export * from "./createOAuthApp.js";
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,4 @@
11
/**
2-
* Used to describe privilege list of an app.
2+
* Used to describe privilege list of an app. For a comlete list of privileges, see the [list of privileges in the security and authentication guide](https://developers.arcgis.com/documentation/security-and-authentication/reference/privileges/#list-of-privileges).
33
*/
4-
export enum Privileges {
5-
Basemaps = "portal:apikey:basemaps",
6-
Demographics = "premium:user:demographics",
7-
Elevation = "premium:user:elevation",
8-
FeatureReport = "premium:user:featurereport",
9-
Geocode = "premium:user:geocode",
10-
GeocodeStored = "premium:user:geocode:stored",
11-
GeocodeTemporary = "premium:user:geocode:temporary",
12-
GeoEnrichment = "premium:user:geoenrichment",
13-
NetworkAnalysis = "premium:user:networkanalysis",
14-
NetworkAnalysisRouting = "premium:user:networkanalysis:routing",
15-
NetworkAnalysisOptimizedRouting = "premium:user:networkanalysis:optimizedrouting",
16-
NetworkAnalysisClosestFacility = "premium:user:networkanalysis:closestfacility",
17-
NetworkAnalysisServiceArea = "premium:user:networkanalysis:servicearea",
18-
NetworkAnalysisLocationalLocation = "premium:user:networkanalysis:locationallocation",
19-
NetworkAnalysisVehicleRouting = "premium:user:networkanalysis:vehiclerouting",
20-
NetworkAnalysisOriginDestinationCostMatrix = "premium:user:networkanalysis:origindestinationcostmatrix",
21-
Places = "premium:user:places",
22-
SpatialAnalysis = "premium:user:spatialanalysis",
23-
GeoAnalytics = "premium:publisher:geoanalytics",
24-
RasterAnalysis = "premium:publisher:rasteranalysis"
25-
}
4+
export type Privileges = string[];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {
2+
request,
3+
IRequestOptions,
4+
IAuthenticationManager
5+
} from "@esri/arcgis-rest-request";
6+
import { getRegisteredAppInfo } from "./getRegisteredAppInfo.js";
7+
import { getPortalUrl } from "@esri/arcgis-rest-portal";
8+
9+
export interface IGenerateApiKeyTokenOptions extends IRequestOptions {
10+
itemId: string;
11+
apiKey: 1 | 2;
12+
portal?: string;
13+
authentication: IAuthenticationManager;
14+
}
15+
16+
export async function generateApiKeyToken(
17+
options: IGenerateApiKeyTokenOptions
18+
): Promise<{ access_token: string; expires_in: number }> {
19+
const portal = getPortalUrl(options);
20+
const url = `${portal}/oauth2/token`;
21+
22+
const appInfo = await getRegisteredAppInfo({
23+
itemId: options.itemId,
24+
authentication: options.authentication
25+
});
26+
27+
const params = {
28+
client_id: appInfo.client_id,
29+
client_secret: appInfo.client_secret,
30+
apiToken: options.apiKey,
31+
regenerateApiToken: true,
32+
grant_type: "client_credentials"
33+
};
34+
35+
return request(url, {
36+
authentication: options.authentication,
37+
params
38+
});
39+
}

0 commit comments

Comments
 (0)