Skip to content

Commit

Permalink
fix(fastly): Return undefined for dict values of write-only edge dicts
Browse files Browse the repository at this point in the history
Getting the value of an edge dictionary value for a write-only dictionary results in an error 400
from the Fastly API, which is correct, but not helpful. Because `readDictItem` always gets the
dictionary metadata before reading, we can guard against this error and return a proper response
(status: 403, item_value: undefined)

fixes #27
  • Loading branch information
trieloff committed Jan 22, 2019
1 parent 436b119 commit ab5972a
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 1 deletion.
18 changes: 17 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,23 @@ class Fastly {
return this.readDictionary(
await this.getVersion(version, 'latest'),
name,
).then(({ data }) => this.request.get(`/service/${this.service_id}/dictionary/${data.id}/item/${key}`));
).then(({ data }) => {
if (data.write_only) {
return {
status: 403, // not permitted to read from write-only dicts
data: {
dictionary_id: data.id,
service_id: this.service_id,
item_key: key,
item_value: undefined,
created_at: undefined,
deleted_at: undefined,
updated_at: undefined,
},
};
}
return this.request.get(`/service/${this.service_id}/dictionary/${data.id}/item/${key}`);
});
}

/**
Expand Down
56 changes: 56 additions & 0 deletions test/readDictItem.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'use strict';

/* eslint-env mocha */

const nock = require('nock');
const expect = require('expect');
const config = require('../src/config');
const fastlyPromises = require('../src/index');
const response = require('./response/dictitem.response');

describe('#readDictItem', () => {
const fastly = fastlyPromises('923b6bd5266a7f932e41962755bd4254', 'SU1Z0isxPaozGVKXdv0eY');
let res;

nock(config.mainEntryPoint)
// get the dictionary first
.get('/service/SU1Z0isxPaozGVKXdv0eY/version/1/dictionary/my_dictionary')
.reply(200, response.dict.get)
// list
.get('/service/SU1Z0isxPaozGVKXdv0eY/dictionary/5clCytcTJrnvPi8wjqPH0q/item/some_key')
.reply(200, response.item.get);

before(async () => {
res = await fastly.readDictItem(1, 'my_dictionary', 'some_key');
});

it('response should be a status 200', () => {
expect(res.status).toBe(200);
});

it('response body should exist', () => {
expect(res.data).toBeTruthy();
});

it('response body should be an object', () => {
expect(typeof res.data).toBe('object');
});

it('response value should match', () => {
expect(res.data.item_value).toBe('some_value');
});

it('response body should contain all properties', () => {
[
'dictionary_id',
'service_id',
'item_key',
'item_value',
'created_at',
'deleted_at',
'updated_at',
].forEach((e) => {
expect(Object.keys(res.data)).toContain(e);
});
});
});
56 changes: 56 additions & 0 deletions test/readDictItem.writeonly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'use strict';

/* eslint-env mocha */

const nock = require('nock');
const expect = require('expect');
const config = require('../src/config');
const fastlyPromises = require('../src/index');
const response = require('./response/dictitem.response');

describe('#readDictItem (write-only)', () => {
const fastly = fastlyPromises('923b6bd5266a7f932e41962755bd4254', 'SU1Z0isxPaozGVKXdv0eY');
let res;

nock(config.mainEntryPoint)
// get the dictionary first
.get('/service/SU1Z0isxPaozGVKXdv0eY/version/1/dictionary/secret_dictionary')
.reply(200, response.dict.getsecret);

before(async () => {
res = await fastly.readDictItem(1, 'secret_dictionary', 'some_key');
});

it('response should be a status 200', () => {
expect(res.status).toBe(403);
});

it('response body should exist', () => {
expect(res.data).toBeTruthy();
});

it('response body should be an object', () => {
expect(typeof res.data).toBe('object');
});

it('response value should match', () => {
expect(res.data.item_value).toBeUndefined();
expect(res.data.created_at).toBeUndefined();
expect(res.data.deleted_at).toBeUndefined();
expect(res.data.updated_at).toBeUndefined();
});

it('response body should contain all properties', () => {
[
'dictionary_id',
'service_id',
'item_key',
'item_value',
'created_at',
'deleted_at',
'updated_at',
].forEach((e) => {
expect(Object.keys(res.data)).toContain(e);
});
});
});
10 changes: 10 additions & 0 deletions test/response/dictitem.response.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ module.exports = {
version: 1,
write_only: false,
},
getsecret: {
created_at: '2016-05-03T16:11:41+00:00',
deleted_at: null,
id: '5clCytcTJrnvPi8wjqPH0q',
name: 'my_dictionary',
service_id: 'SU1Z0isxPaozGVKXdv0eY',
updated_at: '2016-05-03T16:20:35+00:00',
version: 1,
write_only: true,
},
post: {
created_at: '2016-05-03T16:11:41+00:00',
deleted_at: null,
Expand Down

0 comments on commit ab5972a

Please sign in to comment.