Skip to content

Commit

Permalink
add api key permissioning support (#12)
Browse files Browse the repository at this point in the history
* add permissions document support

* add codeowner
  • Loading branch information
cheeseandcereal committed Dec 4, 2019
1 parent 92804f3 commit 24fd57e
Show file tree
Hide file tree
Showing 8 changed files with 588 additions and 575 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @cheeseandcereal @deanshelton913
* @cheeseandcereal @deanshelton913 @rdaquilante
14 changes: 10 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
# Changelog

## 4.1.0
## 4.2.0

- **Feature:**
- Support new permissioning feature for api keys
- **Development:**
- Update development dependencies
- Add rdaquilante as a tertiary code owner

## 4.1.0

- **Feature:**
- Add support for new Binance interchain endpoints with client functions:
- `createBinanceInterchain`
- `updateBinanceInterchain`
- `signBinanceTransaction`

- **Bug Fix**
- **Bug Fix:**
- Remove erroneous `?` from query string when no query string parameters are provided
- Fix typing bug with `getSmartContractObject`

Expand Down Expand Up @@ -50,7 +56,7 @@ Check [the docs](https://node-sdk-docs.dragonchain.com/latest/) for more details
- Add NodeJS 12 to PR checks
- **Packaging:**
- Remove some unnecessary files from the packaged release
- **Bug Fix**
- **Bug Fix:**
- Increase precision on timestamp sent to Dragonchain to prevent replay attack error for subsequent requests

## 3.2.0
Expand Down
30 changes: 15 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dragonchain-sdk",
"version": "4.1.0",
"version": "4.2.0",
"description": "Dragonchain SDK for Node.JS and the Browser",
"license": "Apache-2.0",
"homepage": "https://github.com/dragonchain/dragonchain-sdk-javascript#readme",
Expand Down Expand Up @@ -80,25 +80,25 @@
"tslib": "^1.10.0"
},
"devDependencies": {
"@types/chai": "^4.2.0",
"@types/chai": "^4.2.6",
"@types/ini": "^1.3.30",
"@types/mocha": "^5.2.7",
"@types/node": "^12.7.2",
"@types/node-fetch": "^2.5.0",
"@types/sinon": "^7.0.13",
"@types/node": "^12.12.14",
"@types/node-fetch": "^2.5.4",
"@types/sinon": "^7.5.1",
"@types/sinon-chai": "^3.2.3",
"@typescript-eslint/eslint-plugin": "^2.0.0",
"@typescript-eslint/parser": "^2.0.0",
"@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0",
"chai": "^4.2.0",
"eslint": "^6.2.2",
"eslint-config-prettier": "^6.1.0",
"mocha": "^6.2.0",
"eslint": "^6.7.2",
"eslint-config-prettier": "^6.7.0",
"mocha": "^6.2.2",
"nyc": "^14.1.1",
"prettier": "^1.18.2",
"sinon": "^7.4.1",
"prettier": "^1.19.1",
"sinon": "^7.5.0",
"sinon-chai": "^3.3.0",
"ts-node": "^8.3.0",
"typedoc": "^0.15.0",
"typescript": "^3.5.3"
"ts-node": "^8.5.4",
"typedoc": "^0.15.3",
"typescript": "^3.7.3"
}
}
3 changes: 1 addition & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ import { createClient } from './services/dragonchain-client/DragonchainClient';
/**
* @hidden
*/
// tslint:disable-next-line:no-empty
const nullLog = () => {};
const nullLog = () => {}; // eslint-disable-line @typescript-eslint/no-empty-function
/**
* @hidden
*/
Expand Down
155 changes: 148 additions & 7 deletions src/interfaces/DragonchainClientInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,19 @@ export interface InterchainNetworkList {
* "key": "d5K20n1VfHZYIgk55UdJO0bTyMTnjasdGkNyg66ASnd",
* "id": "PDJSYJNBTDBP",
* "registration_time": 1548604295,
* "nickname": "key1"
* "nickname": "key1",
* "root": false,
* "permissions_document": {
* "version": "1",
* "default_allow": true,
* "permissions": {
* "api_keys": {
* "allow_create": false,
* "allow_update": false,
* "allow_delete": false
* }
* }
* }
* }
* ```
*/
Expand All @@ -333,7 +345,8 @@ export interface CreateAPIKeyResponse {
id: string;
registration_time: number;
nickname: string;
root?: boolean;
root: boolean;
permissions_document: PermissionsDocument;
}

/**
Expand All @@ -356,13 +369,31 @@ export interface DeleteAPIKeyResponse {
* {
* "id": "PDJSYJNBTDBP",
* "registration_time": 1548604295
* "nickname": "",
* "root": false,
* "permissions_document": {
* "version": "1",
* "default_allow": true,
* "permissions": {
* "api_keys": {
* "allow_create": false,
* "allow_update": false,
* "allow_delete": false
* }
* }
* }
* }
* ```
*/
export interface GetAPIKeyResponse {
id: string;
/**
* Unix timestamp (integer) when this key was created. Could be 0 if root key.
*/
registration_time: number;
nickname?: string;
nickname: string;
root: boolean;
permissions_document: PermissionsDocument;
}

/**
Expand All @@ -371,10 +402,17 @@ export interface GetAPIKeyResponse {
*
* {
* "keys": [
* {
* "id": "PDJSYJNBTDBP",
* "registration_time": 1548604295
* }
* {
* "id": "YLDSY14NTNJ8",
* "registration_time": 0
* "nickname": "",
* "root": true,
* "permissions_document": {
* "version": "1",
* "default_allow": true,
* "permissions": {}
* }
* }
* ]
* }
* ```
Expand Down Expand Up @@ -1078,3 +1116,106 @@ export interface TransactionTypeResponse {
export interface TransactionTypeListResponse {
transaction_types: TransactionTypeResponse[];
}

export interface PermissionsDocumentDefaultEndpoint {
allowed: boolean;
}

export interface PermissionsDocument {
version: '1';
default_allow: boolean;
permissions: {
allow_create?: boolean;
allow_read?: boolean;
allow_update?: boolean;
allow_delete?: boolean;
apiKeys?: {
allow_create?: boolean;
allow_read?: boolean;
allow_update?: boolean;
allow_delete?: boolean;
create_api_key?: PermissionsDocumentDefaultEndpoint;
get_api_key?: PermissionsDocumentDefaultEndpoint;
list_api_keys?: PermissionsDocumentDefaultEndpoint;
delete_api_key?: PermissionsDocumentDefaultEndpoint;
update_api_key?: PermissionsDocumentDefaultEndpoint;
};
blocks?: {
allow_create?: boolean;
allow_read?: boolean;
allow_update?: boolean;
allow_delete?: boolean;
get_block?: PermissionsDocumentDefaultEndpoint;
query_blocks?: PermissionsDocumentDefaultEndpoint;
};
interchains?: {
allow_create?: boolean;
allow_read?: boolean;
allow_update?: boolean;
allow_delete?: boolean;
create_interchain?: PermissionsDocumentDefaultEndpoint;
update_interchain?: PermissionsDocumentDefaultEndpoint;
create_interchain_transaction?: PermissionsDocumentDefaultEndpoint;
list_interchains?: PermissionsDocumentDefaultEndpoint;
get_interchain?: PermissionsDocumentDefaultEndpoint;
delete_interchain?: PermissionsDocumentDefaultEndpoint;
get_default_interchain?: PermissionsDocumentDefaultEndpoint;
set_default_interchain?: PermissionsDocumentDefaultEndpoint;
get_interchain_legacy?: PermissionsDocumentDefaultEndpoint;
create_interchain_transaction_legacy?: PermissionsDocumentDefaultEndpoint;
};
misc?: {
allow_create?: boolean;
allow_read?: boolean;
allow_update?: boolean;
allow_delete?: boolean;
get_status?: PermissionsDocumentDefaultEndpoint;
};
contracts?: {
allow_create?: boolean;
allow_read?: boolean;
allow_update?: boolean;
allow_delete?: boolean;
get_contract?: PermissionsDocumentDefaultEndpoint;
get_contract_logs?: PermissionsDocumentDefaultEndpoint;
list_contracts?: PermissionsDocumentDefaultEndpoint;
create_contract?: PermissionsDocumentDefaultEndpoint;
update_contract?: PermissionsDocumentDefaultEndpoint;
delete_contract?: PermissionsDocumentDefaultEndpoint;
get_contract_object?: PermissionsDocumentDefaultEndpoint;
list_contract_objects?: PermissionsDocumentDefaultEndpoint;
};
transactionTypes?: {
allow_create?: boolean;
allow_read?: boolean;
allow_update?: boolean;
allow_delete?: boolean;
create_transaction_type?: PermissionsDocumentDefaultEndpoint;
delete_transaction_type?: PermissionsDocumentDefaultEndpoint;
list_transaction_types?: PermissionsDocumentDefaultEndpoint;
get_transaction_type?: PermissionsDocumentDefaultEndpoint;
};
transactions?: {
allow_create?: boolean;
allow_read?: boolean;
allow_update?: boolean;
allow_delete?: boolean;
create_transaction?: {
allowed?: boolean;
transaction_types?: {
[txn_type: string]: boolean;
};
};
query_transactions?: PermissionsDocumentDefaultEndpoint;
get_transaction?: PermissionsDocumentDefaultEndpoint;
};
verifications?: {
allow_create?: boolean;
allow_read?: boolean;
allow_update?: boolean;
allow_delete?: boolean;
get_verifications?: PermissionsDocumentDefaultEndpoint;
get_pending_verifications?: PermissionsDocumentDefaultEndpoint;
};
};
}
12 changes: 10 additions & 2 deletions src/services/dragonchain-client/DragonchainClient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,8 @@ describe('DragonchainClient', () => {

describe('.createApiKey', () => {
it('calls #fetch() with correct params', async () => {
await client.createApiKey();
const expectedBody = {};
await client.createApiKey({ nickname: 'mynickname', permissionsDocument: { version: '1', default_allow: true, permissions: {} } });
const expectedBody = { nickname: 'mynickname', permissions_document: { version: '1', default_allow: true, permissions: {} } };
assert.calledWith(fetch, 'fakeUrl/v1/api-key', { ...expectedFetchOptions, body: JSON.stringify(expectedBody) });
});
});
Expand Down Expand Up @@ -523,6 +523,14 @@ describe('DragonchainClient', () => {
}
};

describe('.updateApiKey', () => {
it('calls #fetch() with correct params', async () => {
await client.updateApiKey({ keyId: 'someKeyId', nickname: 'mynickname', permissionsDocument: { version: '1', default_allow: true, permissions: {} } });
const expectedBody = { nickname: 'mynickname', permissions_document: { version: '1', default_allow: true, permissions: {} } };
assert.calledWith(fetch, 'fakeUrl/v1/api-key/someKeyId', { ...expectedFetchOptions, body: JSON.stringify(expectedBody) });
});
});

describe('.updateSmartContract', () => {
it('calls #fetch() with correct params', async () => {
const smartContractId = '616152367378';
Expand Down
21 changes: 17 additions & 4 deletions src/services/dragonchain-client/DragonchainClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ import {
CustomTextFieldOptions,
CustomNumberFieldOptions,
CustomTagFieldOptions,
SmartContractLogs
SmartContractLogs,
PermissionsDocument
} from '../../interfaces/DragonchainClientInterfaces';
import { CredentialService, HmacAlgorithm } from '../credential-service/CredentialService';
import { getDragonchainId, getDragonchainEndpoint } from '../config-service';
Expand Down Expand Up @@ -156,10 +157,15 @@ export class DragonchainClient {
* nickname for the newly created key
*/
nickname?: string;
/**
* Permissions document to use with this key
*/
permissionsDocument?: PermissionsDocument;
} = {}
) => {
const body: any = {};
if (options.nickname) body['nickname'] = options.nickname;
if (options.permissionsDocument) body['permissions_document'] = options.permissionsDocument;
return (await this.post('/v1/api-key', body)) as Response<CreateAPIKeyResponse>;
};

Expand Down Expand Up @@ -207,10 +213,17 @@ export class DragonchainClient {
/**
* New nickname to set for key
*/
nickname: string;
nickname?: string;
/**
* New permissions document to assign to this key
*/
permissionsDocument?: PermissionsDocument;
}) => {
if (!options.keyId || !options.nickname) throw new FailureByDesign('PARAM_ERROR', 'Parameter `keyId` and `nickname` are required');
return (await this.put(`/v1/api-key/${options.keyId}`, { nickname: options.nickname })) as Response<SimpleResponse>;
if (!options.keyId) throw new FailureByDesign('PARAM_ERROR', 'Parameter `keyId` is required');
const body: any = {};
if (options.nickname) body['nickname'] = options.nickname;
if (options.permissionsDocument) body['permissions_document'] = options.permissionsDocument;
return (await this.put(`/v1/api-key/${options.keyId}`, body)) as Response<GetAPIKeyResponse>;
};

/**
Expand Down

0 comments on commit 24fd57e

Please sign in to comment.