Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 116 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ const card = await client.accessCards.provision({
email: "employee@yourwebsite.com",
phoneNumber: "+19547212241",
classification: "full_time",
department: "Engineering",
location: "San Francisco",
siteName: "HQ Building A",
workstation: "4F-207",
mailStop: "MS-401",
companyAddress: "123 Main St, San Francisco, CA 94105",
startDate: new Date().toISOString(),
expirationDate: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString(),
employeePhoto: "[image_in_base64_encoded_format]",
Expand Down Expand Up @@ -290,6 +296,37 @@ console.log(`Status: ${result.status}`);

### Webhooks

#### Create a webhook

```javascript
const webhook = await client.console.webhooks.create({
name: 'Production',
url: 'https://example.com/webhooks',
subscribedEvents: ['ag.access_pass.issued']
});

console.log(`Webhook created: ${webhook.id}`);
console.log(`Private key: ${webhook.privateKey}`);
```

#### List webhooks

```javascript
const webhooks = await client.console.webhooks.list();

webhooks.forEach(webhook => {
console.log(`ID: ${webhook.id}, Name: ${webhook.name}`);
});
```

#### Delete a webhook

```javascript
await client.console.webhooks.delete('abc123');
```

#### Receiving webhook payloads

```javascript
const express = require('express');
const app = express();
Expand Down Expand Up @@ -321,6 +358,77 @@ app.post('/webhooks', (req, res) => {
});
```

### Landing Pages

#### List landing pages

```javascript
const landingPages = await client.console.listLandingPages();

landingPages.forEach(page => {
console.log(`ID: ${page.id}, Name: ${page.name}, Kind: ${page.kind}`);
console.log(` Password Protected: ${page.passwordProtected}`);
if (page.logoUrl) console.log(` Logo URL: ${page.logoUrl}`);
});
```

#### Create a landing page

```javascript
const landingPage = await client.console.createLandingPage({
name: "Miami Office Access Pass",
kind: "universal",
additionalText: "Welcome to the Miami Office",
bgColor: "#f1f5f9",
allowImmediateDownload: true
});

console.log(`Landing page created: ${landingPage.id}`);
console.log(`Name: ${landingPage.name}, Kind: ${landingPage.kind}`);
```

#### Update a landing page

```javascript
const landingPage = await client.console.updateLandingPage({
landingPageId: "0xlandingpage1d",
name: "Updated Miami Office Access Pass",
additionalText: "Welcome! Tap below to get your access pass.",
bgColor: "#e2e8f0"
});

console.log(`Landing page updated: ${landingPage.id}`);
console.log(`Name: ${landingPage.name}`);
```

### Credential Profiles

#### List credential profiles

```javascript
const profiles = await client.console.credentialProfiles.list();

profiles.forEach(profile => {
console.log(`ID: ${profile.id}, Name: ${profile.name}, AID: ${profile.aid}`);
});
```

#### Create a credential profile

```javascript
const profile = await client.console.credentialProfiles.create({
name: 'Main Office Profile',
appName: 'KEY-ID-main',
keys: [
{ value: 'your_32_char_hex_master_key_here' },
{ value: 'your_32_char_hex__read_key__here' }
]
});

console.log(`Profile created: ${profile.id}`);
console.log(`AID: ${profile.aid}`);
```

## Configuration

```javascript
Expand Down Expand Up @@ -373,7 +481,14 @@ MIT License - See LICENSE file for details.
| GET /v1/console/pass-template-pairs | `console.listPassTemplatePairs()` | Y |
| GET /v1/console/ledger-items | `console.ledgerItems()` | Y |
| POST .../ios_preflight | `console.iosPreflight()` | Y |
| GET /v1/console/webhooks | `console.webhooks.list()` | Y |
| POST /v1/console/webhooks | `console.webhooks.create()` | Y |
| DELETE /v1/console/webhooks/{id} | `console.webhooks.delete()` | Y |
| GET /v1/console/landing-pages | `console.listLandingPages()` | Y |
| POST /v1/console/landing-pages | `console.createLandingPage()` | Y |
| PUT /v1/console/landing-pages/{id} | `console.updateLandingPage()` | Y |
| GET /v1/console/credential-profiles | `console.credentialProfiles.list()` | Y |
| POST /v1/console/credential-profiles | `console.credentialProfiles.create()` | Y |
| POST /v1/console/hid/orgs | `console.hid.orgs.create()` | Y |
| GET /v1/console/hid/orgs | `console.hid.orgs.list()` | Y |
| POST /v1/console/hid/orgs/activate | `console.hid.orgs.activate()` | Y |
| Webhooks (payload) | CloudEvents receiver | Y |
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "accessgrid",
"version": "1.2.1",
"version": "1.3.0",
"description": "JavaScript SDK for the AccessGrid API",
"main": "dist/index.js",
"module": "dist/index.mjs",
Expand Down
184 changes: 182 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class AccessCard {
this.fileData = data.file_data;
this.directInstallUrl = data.direct_install_url;
this.title = data.title;
this.temporary = data.temporary;
this.employeeId = data.employee_id;
this.organizationName = data.organization_name;
this.createdAt = data.created_at;
this.devices = data.devices || [];
this.metadata = data.metadata || {};
}
Expand Down Expand Up @@ -153,7 +157,7 @@ class BaseApi {
this.accountId = accountId;
this.secretKey = secretKey;
this.baseUrl = baseUrl.replace(/\/$/, ""); // Remove trailing slash if present
this.version = "1.2.0"; // Should come from package.json
this.version = "1.3.0"; // Should come from package.json
}

async request(path, options = {}) {
Expand Down Expand Up @@ -321,6 +325,12 @@ class AccessCardsApi extends BaseApi {
isPassReadyToTransact: "is_pass_ready_to_transact",
tileData: "tile_data",
reservations: "reservations",
department: "department",
location: "location",
siteName: "site_name",
workstation: "workstation",
mailStop: "mail_stop",
companyAddress: "company_address",
siteCode: "site_code",
cardNumber: "card_number",
fileData: "file_data",
Expand Down Expand Up @@ -452,6 +462,12 @@ class ConsoleApi extends BaseApi {
this.hid = {
orgs: new HIDOrgsApi(accountId, secretKey, baseUrl),
};
this.webhooks = new WebhooksApi(accountId, secretKey, baseUrl);
this.credentialProfiles = new CredentialProfilesApi(
accountId,
secretKey,
baseUrl,
);
}

_buildTemplateBody(params) {
Expand Down Expand Up @@ -599,6 +615,63 @@ class ConsoleApi extends BaseApi {
return response;
}

async listLandingPages() {
const response = await this.request("/v1/console/landing-pages");
const pages = Array.isArray(response) ? response : [];
return pages.map((p) => new LandingPage(p));
}

async createLandingPage(params) {
const paramMapping = {
name: "name",
kind: "kind",
additionalText: "additional_text",
bgColor: "bg_color",
allowImmediateDownload: "allow_immediate_download",
password: "password",
is2faEnabled: "is_2fa_enabled",
logo: "logo",
};

const body = {};
for (const [jsKey, apiKey] of Object.entries(paramMapping)) {
if (params[jsKey] !== undefined) {
body[apiKey] = params[jsKey];
}
}

const response = await this.request("/v1/console/landing-pages", {
method: "POST",
body,
});
return new LandingPage(response);
}

async updateLandingPage(params) {
const paramMapping = {
name: "name",
additionalText: "additional_text",
bgColor: "bg_color",
allowImmediateDownload: "allow_immediate_download",
password: "password",
is2faEnabled: "is_2fa_enabled",
logo: "logo",
};

const body = {};
for (const [jsKey, apiKey] of Object.entries(paramMapping)) {
if (params[jsKey] !== undefined) {
body[apiKey] = params[jsKey];
}
}

const response = await this.request(
`/v1/console/landing-pages/${params.landingPageId}`,
{ method: "PUT", body },
);
return new LandingPage(response);
}

async listLedgerItems(params = {}) {
const queryParams = new URLSearchParams();
if (params.page) queryParams.append("page", params.page);
Expand Down Expand Up @@ -648,7 +721,8 @@ class HIDOrgsApi extends BaseApi {

async list() {
const response = await this.request("/v1/console/hid/orgs");
return (response.hid_orgs || []).map((org) => new HIDOrg(org));
const orgs = Array.isArray(response) ? response : response.hid_orgs || [];
return orgs.map((org) => new HIDOrg(org));
}

async activate(params) {
Expand All @@ -663,6 +737,109 @@ class HIDOrgsApi extends BaseApi {
}
}

// LandingPage model class
class LandingPage {
constructor(data = {}) {
this.id = data.id;
this.name = data.name;
this.createdAt = data.created_at;
this.kind = data.kind;
this.passwordProtected = data.password_protected;
this.logoUrl = data.logo_url;
}
}

// CredentialProfile model class
class CredentialProfile {
constructor(data = {}) {
this.id = data.id;
this.aid = data.aid;
this.name = data.name;
this.appleId = data.apple_id;
this.createdAt = data.created_at;
this.cardStorage = data.card_storage;
this.keys = data.keys || [];
this.files = data.files || [];
}
}

// Webhook model class
class Webhook {
constructor(data = {}) {
this.id = data.id;
this.name = data.name;
this.url = data.url;
this.authMethod = data.auth_method;
this.subscribedEvents = data.subscribed_events || [];
this.createdAt = data.created_at;
this.privateKey = data.private_key;
this.clientCert = data.client_cert;
this.certExpiresAt = data.cert_expires_at;
}
}

// Webhooks API handling
class WebhooksApi extends BaseApi {
constructor(accountId, secretKey, baseUrl) {
super(accountId, secretKey, baseUrl);
}

async create(params) {
const body = {
name: params.name,
url: params.url,
subscribed_events: params.subscribedEvents,
};
if (params.authMethod) body.auth_method = params.authMethod;

const response = await this.request("/v1/console/webhooks", {
method: "POST",
body,
});
return new Webhook(response);
}

async list() {
const response = await this.request("/v1/console/webhooks");
const webhooks = response.webhooks || [];
return webhooks.map((w) => new Webhook(w));
}

async delete(webhookId) {
await this.request(`/v1/console/webhooks/${webhookId}`, {
method: "DELETE",
});
}
}

// Credential Profiles API handling
class CredentialProfilesApi extends BaseApi {
constructor(accountId, secretKey, baseUrl) {
super(accountId, secretKey, baseUrl);
}

async create(params) {
const body = {
name: params.name,
app_name: params.appName,
keys: params.keys,
};
if (params.fileId) body.file_id = params.fileId;

const response = await this.request("/v1/console/credential-profiles", {
method: "POST",
body,
});
return new CredentialProfile(response);
}

async list() {
const response = await this.request("/v1/console/credential-profiles");
const profiles = Array.isArray(response) ? response : [];
return profiles.map((p) => new CredentialProfile(p));
}
}

// Main AccessGrid class
class AccessGrid {
constructor(accountId, secretKey, options = {}) {
Expand All @@ -689,6 +866,9 @@ export {
LedgerItem,
LedgerItemAccessPass,
LedgerItemPassTemplate,
LandingPage,
CredentialProfile,
Webhook,
};

// Default export
Expand Down
Loading
Loading