accessgrid 0.2.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +282 -25
- data/lib/accessgrid/access_cards.rb +28 -17
- data/lib/accessgrid/console.rb +354 -23
- data/lib/accessgrid/error.rb +27 -0
- data/lib/accessgrid/request.rb +112 -0
- data/lib/accessgrid/smart_tap_reveal_crypto.rb +78 -0
- data/lib/accessgrid/version.rb +4 -2
- data/lib/accessgrid.rb +65 -136
- metadata +13 -52
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5370a4fedb6bf2bb2dc99ec4a8b28148f1caca417aca9f2401192c06a5fd49f9
|
|
4
|
+
data.tar.gz: fbe42537ec52fef71f1cd9806f2d91896c65e8e2ae4ad08aa8b9b864c52cf6aa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c98e6d776bd2eede74712e6a6a08d0b87c67cc2161dc18748d84db28f34273b69aa6f8f2ce4d6bdb0a5f02c6a68a60cf1b043bed9a785402a373a3296e72521e
|
|
7
|
+
data.tar.gz: 6d8c089a3071b4064a5902823cfd8f88393fd0d60d80215a72860dd6e139d1a790b4a8a5b410a3311d54915b6a6c1fe94c7c3cc023d33c0a74691e2c886c1a1d
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# AccessGrid
|
|
1
|
+
# 
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AccessGrid is a Ruby SDK for interacting with the [AccessGrid.com](https://www.accessgrid.com) API. This SDK provides a simple interface for managing NFC key cards and enterprise templates. Full docs at https://www.accessgrid.com/docs
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -43,15 +43,25 @@ client = AccessGrid.new(account_id, secret_key)
|
|
|
43
43
|
card = client.access_cards.issue(
|
|
44
44
|
card_template_id: card_template_id,
|
|
45
45
|
employee_id: "123456789",
|
|
46
|
-
card_number: "16187",
|
|
47
46
|
tag_id: "DDEADB33FB00B5",
|
|
48
47
|
full_name: "Employee name",
|
|
49
48
|
email: "employee@yourwebsite.com",
|
|
50
49
|
phone_number: "+19547212241",
|
|
51
50
|
classification: "full_time",
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
department: "Engineering",
|
|
52
|
+
location: "San Francisco",
|
|
53
|
+
site_name: "HQ Building A",
|
|
54
|
+
workstation: "4F-207",
|
|
55
|
+
mail_stop: "MS-401",
|
|
56
|
+
company_address: "123 Main St, San Francisco, CA 94105",
|
|
57
|
+
start_date: Time.now.utc.iso8601(3),
|
|
58
|
+
expiration_date: 3.months.from_now.utc.iso8601(3),
|
|
59
|
+
employee_photo: "[image_in_base64_encoded_format]",
|
|
60
|
+
title: "Engineering Manager",
|
|
61
|
+
metadata: {
|
|
62
|
+
"department": "engineering",
|
|
63
|
+
"badge_type": "contractor"
|
|
64
|
+
}
|
|
55
65
|
)
|
|
56
66
|
|
|
57
67
|
# Provision is an alias for issue (for backwards compatibility)
|
|
@@ -127,27 +137,24 @@ client.access_cards.delete("0xc4rd1d")
|
|
|
127
137
|
|
|
128
138
|
```ruby
|
|
129
139
|
template = client.console.create_template(
|
|
130
|
-
name: "Employee
|
|
140
|
+
name: "Employee Access Pass",
|
|
131
141
|
platform: "apple",
|
|
132
|
-
use_case: "
|
|
142
|
+
use_case: "corporate_id",
|
|
133
143
|
protocol: "desfire",
|
|
134
144
|
allow_on_multiple_devices: true,
|
|
135
145
|
watch_count: 2,
|
|
136
146
|
iphone_count: 3,
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
support_email: "support@yourcompany.com",
|
|
149
|
-
privacy_policy_url: "https://yourcompany.com/privacy",
|
|
150
|
-
terms_and_conditions_url: "https://yourcompany.com/terms"
|
|
147
|
+
background_color: "#FFFFFF",
|
|
148
|
+
label_color: "#000000",
|
|
149
|
+
label_secondary_color: "#333333",
|
|
150
|
+
support_url: "https://help.yourcompany.com",
|
|
151
|
+
support_phone_number: "+1-555-123-4567",
|
|
152
|
+
support_email: "support@yourcompany.com",
|
|
153
|
+
privacy_policy_url: "https://yourcompany.com/privacy",
|
|
154
|
+
terms_and_conditions_url: "https://yourcompany.com/terms",
|
|
155
|
+
metadata: {
|
|
156
|
+
version: "2.1",
|
|
157
|
+
approval_status: "approved"
|
|
151
158
|
}
|
|
152
159
|
)
|
|
153
160
|
```
|
|
@@ -159,7 +166,6 @@ template = client.console.update_template(
|
|
|
159
166
|
"0xd3adb00b5",
|
|
160
167
|
{
|
|
161
168
|
name: "Updated Employee NFC key",
|
|
162
|
-
allow_on_multiple_devices: true,
|
|
163
169
|
watch_count: 2,
|
|
164
170
|
iphone_count: 3,
|
|
165
171
|
support_info: {
|
|
@@ -179,6 +185,30 @@ template = client.console.update_template(
|
|
|
179
185
|
template = client.console.read_template("0xd3adb00b5")
|
|
180
186
|
```
|
|
181
187
|
|
|
188
|
+
#### Publish a template
|
|
189
|
+
|
|
190
|
+
```ruby
|
|
191
|
+
result = client.console.publish_template("0xd3adb00b5")
|
|
192
|
+
|
|
193
|
+
puts result.id # "0xd3adb00b5"
|
|
194
|
+
puts result.status # "in-review" (Apple), "ready" (Android), or "publishing" (already in flight)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
#### Reveal a SmartTap private key
|
|
198
|
+
|
|
199
|
+
Fetches the template's SmartTap private key, decrypted client-side. The SDK generates a fresh ephemeral P-256 keypair per call, submits the public half, and decrypts the server's response — you get the plaintext PEM back without touching any crypto.
|
|
200
|
+
|
|
201
|
+
```ruby
|
|
202
|
+
reveal = client.console.reveal_smart_tap("0xd3adb00b5")
|
|
203
|
+
|
|
204
|
+
puts "Key version: #{reveal.key_version}"
|
|
205
|
+
puts "Collector ID: #{reveal.collector_id}"
|
|
206
|
+
puts "Fingerprint: #{reveal.fingerprint}"
|
|
207
|
+
puts reveal.private_key # PEM — store in your reader/collector key vault
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
The server enforces single-use on pubkey fingerprint and rate-limits to 1 per minute per account. The SDK uses a fresh keypair every call, so single-use is satisfied automatically. Errors raised by the crypto path (`AccessGrid::DecryptError`, `AccessGrid::InvalidEnvelopeError`) and the HTTP path (`AccessGrid::AuthenticationError`, `AccessGrid::ResourceNotFoundError`, etc.) all descend from `AccessGrid::Error`.
|
|
211
|
+
|
|
182
212
|
#### Get event logs
|
|
183
213
|
|
|
184
214
|
```ruby
|
|
@@ -205,6 +235,199 @@ events = client.console.event_log(
|
|
|
205
235
|
)
|
|
206
236
|
```
|
|
207
237
|
|
|
238
|
+
#### List pass template pairs
|
|
239
|
+
|
|
240
|
+
```ruby
|
|
241
|
+
response = client.console.list_pass_template_pairs(page: 1, per_page: 20)
|
|
242
|
+
|
|
243
|
+
response['card_template_pairs'].each do |pair|
|
|
244
|
+
puts "#{pair.name} (#{pair.id})"
|
|
245
|
+
puts " iOS: #{pair.ios_template&.name}"
|
|
246
|
+
puts " Android: #{pair.android_template&.name}"
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
puts response['pagination'] # { "current_page" => 1, "total_pages" => 5, ... }
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
#### List ledger items
|
|
253
|
+
|
|
254
|
+
```ruby
|
|
255
|
+
response = client.console.list_ledger_items(
|
|
256
|
+
page: 1,
|
|
257
|
+
per_page: 50,
|
|
258
|
+
start_date: '2025-01-01T00:00:00Z',
|
|
259
|
+
end_date: '2025-06-30T23:59:59Z'
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
response['ledger_items'].each do |item|
|
|
263
|
+
puts "#{item.kind}: #{item.amount} (#{item.created_at})"
|
|
264
|
+
|
|
265
|
+
if item.access_pass
|
|
266
|
+
puts " Pass: #{item.access_pass.full_name} (#{item.access_pass.state})"
|
|
267
|
+
if item.access_pass.pass_template
|
|
268
|
+
puts " Template: #{item.access_pass.pass_template.name}"
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
puts response['pagination'] # { "current_page" => 1, "total_pages" => 3, ... }
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
#### iOS In-App Provisioning Preflight
|
|
277
|
+
|
|
278
|
+
```ruby
|
|
279
|
+
response = client.console.ios_preflight(
|
|
280
|
+
card_template_id: "0xt3mp14t3-3x1d",
|
|
281
|
+
access_pass_ex_id: "0xp455-3x1d"
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
puts "Provisioning Credential ID: #{response.provisioning_credential_identifier}"
|
|
285
|
+
puts "Sharing Instance ID: #{response.sharing_instance_identifier}"
|
|
286
|
+
puts "Card Template ID: #{response.card_template_identifier}"
|
|
287
|
+
puts "Environment ID: #{response.environment_identifier}"
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Webhooks
|
|
291
|
+
|
|
292
|
+
#### Create a webhook
|
|
293
|
+
|
|
294
|
+
```ruby
|
|
295
|
+
webhook = client.console.webhooks.create(
|
|
296
|
+
name: 'Production',
|
|
297
|
+
url: 'https://example.com/webhooks',
|
|
298
|
+
subscribed_events: ['ag.access_pass.issued']
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
puts "Webhook created: #{webhook.id}"
|
|
302
|
+
puts "Private key: #{webhook.private_key}"
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### List webhooks
|
|
306
|
+
|
|
307
|
+
```ruby
|
|
308
|
+
webhooks = client.console.webhooks.list
|
|
309
|
+
|
|
310
|
+
webhooks.each do |webhook|
|
|
311
|
+
puts "ID: #{webhook.id}, Name: #{webhook.name}"
|
|
312
|
+
end
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### Delete a webhook
|
|
316
|
+
|
|
317
|
+
```ruby
|
|
318
|
+
client.console.webhooks.delete('abc123')
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### HID Organizations
|
|
322
|
+
|
|
323
|
+
#### Create an HID org
|
|
324
|
+
|
|
325
|
+
```ruby
|
|
326
|
+
org = client.console.hid.orgs.create(
|
|
327
|
+
name: 'My Org',
|
|
328
|
+
full_address: '1 Main St, NY NY',
|
|
329
|
+
phone: '+1-555-0000',
|
|
330
|
+
first_name: 'Ada',
|
|
331
|
+
last_name: 'Lovelace'
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
puts "Created org: #{org.name} (ID: #{org.id})"
|
|
335
|
+
puts "Slug: #{org.slug}"
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
#### List HID orgs
|
|
339
|
+
|
|
340
|
+
```ruby
|
|
341
|
+
orgs = client.console.hid.orgs.list
|
|
342
|
+
|
|
343
|
+
orgs.each do |org|
|
|
344
|
+
puts "Org ID: #{org.id}, Name: #{org.name}, Slug: #{org.slug}"
|
|
345
|
+
end
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
#### Activate an HID org
|
|
349
|
+
|
|
350
|
+
```ruby
|
|
351
|
+
result = client.console.hid.orgs.activate(
|
|
352
|
+
email: 'admin@example.com',
|
|
353
|
+
password: 'hid-password-123'
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
puts "Completed registration for org: #{result.name}"
|
|
357
|
+
puts "Status: #{result.status}"
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Landing Pages
|
|
361
|
+
|
|
362
|
+
#### List landing pages
|
|
363
|
+
|
|
364
|
+
```ruby
|
|
365
|
+
landing_pages = client.console.list_landing_pages
|
|
366
|
+
|
|
367
|
+
landing_pages.each do |page|
|
|
368
|
+
puts "ID: #{page.id}, Name: #{page.name}, Kind: #{page.kind}"
|
|
369
|
+
puts " Password Protected: #{page.password_protected}"
|
|
370
|
+
puts " Logo URL: #{page.logo_url}" if page.logo_url
|
|
371
|
+
end
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### Create a landing page
|
|
375
|
+
|
|
376
|
+
```ruby
|
|
377
|
+
landing_page = client.console.create_landing_page(
|
|
378
|
+
name: "Miami Office Access Pass",
|
|
379
|
+
kind: "universal",
|
|
380
|
+
additional_text: "Welcome to the Miami Office",
|
|
381
|
+
bg_color: "#f1f5f9",
|
|
382
|
+
allow_immediate_download: true
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
puts "Landing page created: #{landing_page.id}"
|
|
386
|
+
puts "Name: #{landing_page.name}, Kind: #{landing_page.kind}"
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
#### Update a landing page
|
|
390
|
+
|
|
391
|
+
```ruby
|
|
392
|
+
landing_page = client.console.update_landing_page(
|
|
393
|
+
landing_page_id: "0xlandingpage1d",
|
|
394
|
+
name: "Updated Miami Office Access Pass",
|
|
395
|
+
additional_text: "Welcome! Tap below to get your access pass.",
|
|
396
|
+
bg_color: "#e2e8f0"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
puts "Landing page updated: #{landing_page.id}"
|
|
400
|
+
puts "Name: #{landing_page.name}"
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Credential Profiles
|
|
404
|
+
|
|
405
|
+
#### List credential profiles
|
|
406
|
+
|
|
407
|
+
```ruby
|
|
408
|
+
profiles = client.console.credential_profiles.list
|
|
409
|
+
|
|
410
|
+
profiles.each do |profile|
|
|
411
|
+
puts "ID: #{profile.id}, Name: #{profile.name}, AID: #{profile.aid}"
|
|
412
|
+
end
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
#### Create a credential profile
|
|
416
|
+
|
|
417
|
+
```ruby
|
|
418
|
+
profile = client.console.credential_profiles.create(
|
|
419
|
+
name: 'Main Office Profile',
|
|
420
|
+
app_name: 'KEY-ID-main',
|
|
421
|
+
keys: [
|
|
422
|
+
{ value: 'your_32_char_hex_master_key_here' },
|
|
423
|
+
{ value: 'your_32_char_hex__read_key__here' }
|
|
424
|
+
]
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
puts "Profile created: #{profile.id}"
|
|
428
|
+
puts "AID: #{profile.aid}"
|
|
429
|
+
```
|
|
430
|
+
|
|
208
431
|
## Configuration
|
|
209
432
|
|
|
210
433
|
The SDK can be configured with a custom API endpoint:
|
|
@@ -242,7 +465,7 @@ end
|
|
|
242
465
|
|
|
243
466
|
## Requirements
|
|
244
467
|
|
|
245
|
-
- Ruby 2.
|
|
468
|
+
- Ruby 2.19 or higher
|
|
246
469
|
|
|
247
470
|
## Security
|
|
248
471
|
|
|
@@ -262,6 +485,40 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
|
262
485
|
|
|
263
486
|
Bug reports and pull requests are welcome on GitHub at https://github.com/access-grid/accessgrid-rb.
|
|
264
487
|
|
|
488
|
+
## Feature Matrix
|
|
489
|
+
|
|
490
|
+
| Endpoint | Method | Supported |
|
|
491
|
+
|---|---|:---:|
|
|
492
|
+
| POST /v1/key-cards | `access_cards.issue()` | Y |
|
|
493
|
+
| GET /v1/key-cards/{id} | `access_cards.get()` | Y |
|
|
494
|
+
| PATCH /v1/key-cards/{id} | `access_cards.update()` | Y |
|
|
495
|
+
| GET /v1/key-cards | `access_cards.list()` | Y |
|
|
496
|
+
| POST /v1/key-cards/{id}/suspend | `access_cards.suspend()` | Y |
|
|
497
|
+
| POST /v1/key-cards/{id}/resume | `access_cards.resume()` | Y |
|
|
498
|
+
| POST /v1/key-cards/{id}/unlink | `access_cards.unlink()` | Y |
|
|
499
|
+
| POST /v1/key-cards/{id}/delete | `access_cards.delete()` | Y |
|
|
500
|
+
| POST /v1/console/card-templates | `console.create_template()` | Y |
|
|
501
|
+
| PUT /v1/console/card-templates/{id} | `console.update_template()` | Y |
|
|
502
|
+
| GET /v1/console/card-templates/{id} | `console.read_template()` | Y |
|
|
503
|
+
| GET /v1/console/card-templates/{id}/logs | `console.get_logs()` / `console.event_log()` | Y |
|
|
504
|
+
| GET /v1/console/card-template-pairs | `console.list_pass_template_pairs()` | Y |
|
|
505
|
+
| POST /v1/console/card-template-pairs | `console.create_pass_template_pair()` | Y |
|
|
506
|
+
| POST /v1/console/card-templates/{id}/ios_preflight | `console.ios_preflight()` | Y |
|
|
507
|
+
| POST /v1/console/card-templates/{id}/publish | `console.publish_template()` | Y |
|
|
508
|
+
| POST /v1/console/card-templates/{id}/smart-tap/reveal | `console.reveal_smart_tap()` | Y |
|
|
509
|
+
| GET /v1/console/ledger-items | `console.list_ledger_items()` / `console.ledger_items()` | Y |
|
|
510
|
+
| GET /v1/console/webhooks | `console.webhooks.list()` | Y |
|
|
511
|
+
| POST /v1/console/webhooks | `console.webhooks.create()` | Y |
|
|
512
|
+
| DELETE /v1/console/webhooks/{id} | `console.webhooks.delete()` | Y |
|
|
513
|
+
| GET /v1/console/landing-pages | `console.list_landing_pages()` | Y |
|
|
514
|
+
| POST /v1/console/landing-pages | `console.create_landing_page()` | Y |
|
|
515
|
+
| PUT /v1/console/landing-pages/{id} | `console.update_landing_page()` | Y |
|
|
516
|
+
| GET /v1/console/credential-profiles | `console.credential_profiles.list()` | Y |
|
|
517
|
+
| POST /v1/console/credential-profiles | `console.credential_profiles.create()` | Y |
|
|
518
|
+
| POST /v1/console/hid/orgs | `console.hid.orgs.create()` | Y |
|
|
519
|
+
| POST /v1/console/hid/orgs/activate | `console.hid.orgs.activate()` | Y |
|
|
520
|
+
| GET /v1/console/hid/orgs | `console.hid.orgs.list()` | Y |
|
|
521
|
+
|
|
265
522
|
## License
|
|
266
523
|
|
|
267
|
-
The gem is available as open source under the terms of the MIT License.
|
|
524
|
+
The gem is available as open source under the terms of the MIT License.
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# lib/accessgrid/access_cards.rb
|
|
2
4
|
module AccessGrid
|
|
5
|
+
# Manages NFC key card lifecycle operations.
|
|
3
6
|
class AccessCards
|
|
4
7
|
def initialize(client)
|
|
5
8
|
@client = client
|
|
@@ -9,7 +12,7 @@ module AccessGrid
|
|
|
9
12
|
response = @client.make_request(:post, '/v1/key-cards', params)
|
|
10
13
|
Card.new(response)
|
|
11
14
|
end
|
|
12
|
-
|
|
15
|
+
|
|
13
16
|
# Alias provision to issue for backward compatibility
|
|
14
17
|
alias provision issue
|
|
15
18
|
|
|
@@ -22,24 +25,15 @@ module AccessGrid
|
|
|
22
25
|
response = @client.make_request(:patch, "/v1/key-cards/#{card_id}", params)
|
|
23
26
|
Card.new(response)
|
|
24
27
|
end
|
|
25
|
-
|
|
28
|
+
|
|
26
29
|
def list(template_id, state = nil)
|
|
27
30
|
params = { template_id: template_id }
|
|
28
31
|
params[:state] = state if state
|
|
29
|
-
|
|
32
|
+
|
|
30
33
|
response = @client.make_request(:get, '/v1/key-cards', nil, params)
|
|
31
34
|
response.fetch('keys', []).map { |item| Card.new(item) }
|
|
32
35
|
end
|
|
33
36
|
|
|
34
|
-
private def manage_state(card_id, action)
|
|
35
|
-
response = @client.make_request(
|
|
36
|
-
:post,
|
|
37
|
-
"/v1/key-cards/#{card_id}/#{action}",
|
|
38
|
-
{}
|
|
39
|
-
)
|
|
40
|
-
Card.new(response)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
37
|
def suspend(card_id)
|
|
44
38
|
manage_state(card_id, 'suspend')
|
|
45
39
|
end
|
|
@@ -51,23 +45,36 @@ module AccessGrid
|
|
|
51
45
|
def unlink(card_id)
|
|
52
46
|
manage_state(card_id, 'unlink')
|
|
53
47
|
end
|
|
54
|
-
|
|
48
|
+
|
|
55
49
|
def delete(card_id)
|
|
56
50
|
manage_state(card_id, 'delete')
|
|
57
51
|
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def manage_state(card_id, action)
|
|
56
|
+
response = @client.make_request(
|
|
57
|
+
:post,
|
|
58
|
+
"/v1/key-cards/#{card_id}/#{action}"
|
|
59
|
+
)
|
|
60
|
+
Card.new(response)
|
|
61
|
+
end
|
|
58
62
|
end
|
|
59
63
|
|
|
64
|
+
# Represents an NFC key card with its attributes and state.
|
|
60
65
|
class Card
|
|
61
66
|
attr_reader :id, :state, :url, :install_url, :details, :full_name,
|
|
62
67
|
:expiration_date, :card_template_id, :card_number, :site_code,
|
|
63
|
-
:file_data, :direct_install_url, :devices, :metadata
|
|
68
|
+
:file_data, :direct_install_url, :devices, :metadata, :temporary,
|
|
69
|
+
:employee_id, :organization_name, :created_at
|
|
64
70
|
|
|
65
71
|
def initialize(data)
|
|
66
72
|
data ||= {}
|
|
73
|
+
install_url = data.fetch('install_url', nil)
|
|
67
74
|
@id = data.fetch('id', nil)
|
|
68
75
|
@state = data.fetch('state', nil)
|
|
69
|
-
@url =
|
|
70
|
-
@install_url =
|
|
76
|
+
@url = install_url
|
|
77
|
+
@install_url = install_url
|
|
71
78
|
@details = data.fetch('details', nil)
|
|
72
79
|
@full_name = data.fetch('full_name', nil)
|
|
73
80
|
@expiration_date = data.fetch('expiration_date', nil)
|
|
@@ -78,6 +85,10 @@ module AccessGrid
|
|
|
78
85
|
@direct_install_url = data.fetch('direct_install_url', nil)
|
|
79
86
|
@devices = data.fetch('devices', [])
|
|
80
87
|
@metadata = data.fetch('metadata', {})
|
|
88
|
+
@temporary = data.fetch('temporary', nil)
|
|
89
|
+
@employee_id = data.fetch('employee_id', nil)
|
|
90
|
+
@organization_name = data.fetch('organization_name', nil)
|
|
91
|
+
@created_at = data.fetch('created_at', nil)
|
|
81
92
|
end
|
|
82
93
|
|
|
83
94
|
def to_s
|
|
@@ -86,4 +97,4 @@ module AccessGrid
|
|
|
86
97
|
|
|
87
98
|
alias inspect to_s
|
|
88
99
|
end
|
|
89
|
-
end
|
|
100
|
+
end
|