diff --git a/examples/addresses.js b/examples/addresses.js new file mode 100644 index 00000000..66b007f6 --- /dev/null +++ b/examples/addresses.js @@ -0,0 +1,31 @@ +var Plivo = require('../dist/rest/client.js'); +var fs = require('fs') +var client = new Plivo.Client(); + +client.addresses.create("en-US", "Mr", "first_name", "last_name", "address_line1", "address_line2", "New York", "Region", "Postal Code", "nation_id", + { + file: fs.createReadStream(__dirname + '/../jpg.jpg'), + // callback_url: 'https://putsreq.com/tkbaN78VBDDgaYgxILzk', + }) + .then(function(address) { + console.log("\n============ created ===========\n", address) + return client.addresses.list(); + }) + .then(function(addresses) { + console.log("\n============ All Address ===========\n", addresses) + return client.addresses.get(addresses[0].id); + }) + .then(function(address){ + console.log("\n============ list with id ===========\n", address) + return address.delete(); + }) + .then(function(result){ + console.log("\n============ deleted ===========\n", result) + return client.addresses.list() + }) + .then(function(addresss){ + console.log("\n============ list all ===========\n", addresss) + }) + .catch(function(response) { + console.log("\n============ Error :: ===========\n", response); + }); diff --git a/examples/identities.js b/examples/identities.js new file mode 100644 index 00000000..6b03aaae --- /dev/null +++ b/examples/identities.js @@ -0,0 +1,31 @@ +var Plivo = require('../dist/rest/client.js'); +var fs = require('fs') +var client = new Plivo.Client(); + +client.identities.create(null, "Mr", "first_name", "last_name", "birth_place", "1984-12-12", "nationality", "id_nationality", "1999-12-12", "id_type", "id_number", "address_line1", "address_line2", "city", "Region", "Postal Code", + { + file: fs.createReadStream(__dirname + '/../jpg.jpg'), + // callback_url: 'https://putsreq.com/tkbaN78VBDDgaYgxILzk', + }) + .then(function(identities) { + console.log("\n============ created ===========\n", identities) + return client.identities.list(); + }) + .then(function(identities) { + console.log("\n============ All identities ===========\n", identities) + return client.identities.get(identities[0].id); + }) + .then(function(identities){ + console.log("\n============ list with id ===========\n", identities) + return identities.delete(); + }) + .then(function(result){ + console.log("\n============ deleted ===========\n", result) + return client.identities.list() + }) + .then(function(identities){ + console.log("\n============ list all ===========\n", identities) + }) + .catch(function(response) { + console.log("\n============ Error :: ===========\n", response); + }); diff --git a/lib/resources/addresses.js b/lib/resources/addresses.js new file mode 100644 index 00000000..da611b74 --- /dev/null +++ b/lib/resources/addresses.js @@ -0,0 +1,192 @@ +import {extend, validate} from '../utils/common.js'; +import {PlivoResource, PlivoResourceInterface} from '../base'; + +const clientKey = Symbol(); +const action = 'Verification/Address/'; +const idField = 'id'; + +/** + * Represents a Address + * @constructor + * @param {function} client - make api call + * @param {object} [data] - data of call + */ +export class Address extends PlivoResource { + constructor(client, data = {}) { + super(action, Address, idField, client); + + if (idField in data) { + this.id = data[idField]; + } + + extend(this, data); + } + +/** + * update Address + * @method + * @param {object} params - to update Address + * @param {string} [params.country_iso] Country ISO 2 code. + * @param {string} [params.alias] Alias name of the addressT. + * @param {string} [params.salutation] This can have values: Mr, Ms. + * @param {string} [params.first_name] First name of the user for whom the identity is created. + * @param {string} [params.last_name] Second name of the user for whom the identity is created. + * @param {string} [params.address_line1] Building name/number. + * @param {string} [params.address_line2] The street name/number of the address. + * @param {string} [params.city] The city of the address for which the address proof is created. + * @param {string} [params.region] The region of the address for which the address proof is created. + * @param {string} [params.postal_code] The postal code of the address that is being created. + * @param {object} [params.file] A File to upload, which needs to be considered the proof of address. Max. file Size = 5 MB. File should be in jpg, pdf, or png format. + * @param {string} [params.address_proof_type] The type of document that is provided as address proof. Possible values: national_id - National ID document, passport - Passport, business_id - Business registration document, NIF - National identity card for Spain, NIE - Tax identification number for Spain, DNI - Fiscal identification number for Spain, any - Any type of document apart from the ones specified. + * @param {string} [params.fiscal_identification_code] The code is valid for businesses alone. + * @param {string} [params.street_code] Street code of the address. + * @param {string} [params.municipal_code] Municipal code of the address. + * @promise {object} return {@link Address} object + * @fail {Error} return Error + */ + + update(params) { + return super.update(params); + } + +/** + * delete Address + * @method + * @promise {object} return true on success + * @fail {Error} return Error + */ + delete() { + return super.delete(); + } + +} +/** + * Represents a Address interface + * @constructor + * @param {function} client - make api call + * @param {object} [data] - data of call + */ +export class AddressInterface extends PlivoResourceInterface { + + constructor(client, data = {}) { + super(action, Address, idField, client); + extend(this, data); + + this[clientKey] = client; + } + +/** + * get Address by given id + * @method + * @param {string} id - id of Address + * @promise {object} return {@link Address} object + * @fail {Error} return Error + */ + get(id) { + return super.get(id); + } + +/** + * create Address + * @method + * @param {string} country_iso Country ISO 2 code. + * @param {string} salutation This can have values: Mr, Ms. + * @param {string} first_name First name of the user for whom the identity is created. + * @param {string} last_name Second name of the user for whom the identity is created. + * @param {string} address_line1 Building name/number. + * @param {string} address_line2 The street name/number of the address. + * @param {string} city The city of the address for which the address proof is created. + * @param {string} region The region of the address for which the address proof is created. + * @param {string} postal_code The postal code of the address that is being created. + * @param {string} address_proof_type The type of document that is provided as address proof. Possible values: national_id - National ID document, passport - Passport, business_id - Business registration document, NIF - National identity card for Spain, NIE - Tax identification number for Spain, DNI - Fiscal identification number for Spain, any - Any type of document apart from the ones specified. + * @param {object} params - to create Address + * @param {string} [params.alias] Alias name of the addressT. + * @param {object} [params.file] A File to upload, which needs to be considered the proof of address. Max. file Size = 5 MB. File should be in jpg, pdf, or png format. + * @param {string} [params.fiscal_identification_code] The code is valid for businesses alone. + * @param {string} [params.street_code] Street code of the address. + * @param {string} [params.municipal_code] Municipal code of the address. + * @promise {object} return {@link PlivoGenericResponse} object + * @fail {Error} return Error + */ + create(country_iso, salutation, first_name, last_name, address_line1, address_line2, city, region, postal_code, address_proof_type, params = {}) { + + let errors = validate([ + {field: 'country_iso', value: country_iso, validators: ['isRequired', 'isString']}, + {field: 'salutation', value: salutation, validators: ['isRequired', 'isString']}, + {field: 'first_name', value: first_name, validators: ['isRequired', 'isString']}, + {field: 'last_name', value: last_name, validators: ['isRequired', 'isString']}, + {field: 'address_line1', value: address_line1, validators: ['isRequired', 'isString']}, + {field: 'address_line2', value: address_line2, validators: ['isRequired', 'isString']}, + {field: 'city', value: city, validators: ['isRequired', 'isString']}, + {field: 'region', value: region, validators: ['isRequired', 'isString']}, + {field: 'postal_code', value: postal_code, validators: ['isRequired', 'isString']}, + {field: 'address_proof_type', value: address_proof_type, validators: ['isRequired', 'isString']} + ]); + + if (errors) { + return errors; + } + + params.country_iso = country_iso; + params.salutation = salutation; + params.first_name = first_name; + params.last_name = last_name; + params.address_line1 = address_line1; + params.address_line2 = address_line2; + params.city = city; + params.region = region; + params.postal_code = postal_code; + params.address_proof_type = address_proof_type; + + return super.create(params); + } + +/** + * update Address + * @method + * @param {string} id - id of Address + * @param {object} params - to update Address + * @param {string} [params.country_iso] Country ISO 2 code. + * @param {string} [params.alias] Alias name of the addressT. + * @param {string} [params.salutation] This can have values: Mr, Ms. + * @param {string} [params.first_name] First name of the user for whom the identity is created. + * @param {string} [params.last_name] Second name of the user for whom the identity is created. + * @param {string} [params.address_line1] Building name/number. + * @param {string} [params.address_line2] The street name/number of the address. + * @param {string} [params.city] The city of the address for which the address proof is created. + * @param {string} [params.region] The region of the address for which the address proof is created. + * @param {string} [params.postal_code] The postal code of the address that is being created. + * @param {object} [params.file] A File to upload, which needs to be considered the proof of address. Max. file Size = 5 MB. File should be in jpg, pdf, or png format. + * @param {string} [params.address_proof_type] The type of document that is provided as address proof. Possible values: national_id - National ID document, passport - Passport, business_id - Business registration document, NIF - National identity card for Spain, NIE - Tax identification number for Spain, DNI - Fiscal identification number for Spain, any - Any type of document apart from the ones specified. + * @param {string} [params.fiscal_identification_code] The code is valid for businesses alone. + * @param {string} [params.street_code] Street code of the address. + * @param {string} [params.municipal_code] Municipal code of the address. + * @promise {object} return {@link Address} object + * @fail {Error} return Error + */ + update(id, params) { + let errors = validate([ + {field: 'id', value: id, validators: ['isRequired']} + ]); + + if (errors) { + return errors; + } + return new Address(this[clientKey], { + id: id + }).update(params); + } + +/** + * delete Address + * @method + * @param {string} id - id of Address + * @promise {object} return true on success + * @fail {Error} return Error + */ + delete(id) { + return new Address(this[clientKey], { + id: id + }).delete(); + } +} diff --git a/lib/resources/identities.js b/lib/resources/identities.js new file mode 100644 index 00000000..9e21afcb --- /dev/null +++ b/lib/resources/identities.js @@ -0,0 +1,245 @@ +import {extend, validate} from '../utils/common.js'; +import {PlivoResource, PlivoResourceInterface} from '../base'; + +const clientKey = Symbol(); +const action = 'Verification/Identity/'; +const idField = 'id'; + +/** + * Represents a Identity + * @constructor + * @param {function} client - make api call + * @param {object} [data] - data of call + */ +export class Identity extends PlivoResource { + constructor(client, data = {}) { + super(action, Identity, idField, client); + + if (idField in data) { + this.id = data[idField]; + } + + extend(this, data); + } + +/** + * update Identity + * @method + * @param {object} params - to update Identity + * @param {string} [params.country_iso] Country ISO 2 code. + * @param {string} [params.alias] Alias name of the Identity. + * @param {string} [params.salutation] This can have values: Mr, Ms. + * @param {string} [params.first_name] First name of the user for whom the identity is created. + * @param {string} [params.last_name] Second name of the user for whom the identity is created. + * @param {string} [params.birth_place] Birthplace of the user for whom the identity is created. + * @param {string} [params.birth_date] Birth date in yyyy-mm-dd format of the user for whom the identity is created. + * @param {string} [params.nationality] Nationality of the user for whom the identity is created. + * @param {string} [params.id_nationality] Nationality mentioned in the identity proof. + * @param {string} [params.id_issue_date] Issue date in yyyy-mm-dd mentioned in the identity proof. + * @param {string} [params.business_name] Business name of the user for whom the identity is created. + * @param {string} [params.id_type] Building name/number. + * @param {string} [params.id_number] The unique number on the identifier. + * @param {string} [params.address_line1] Building name/number. + * @param {string} [params.address_line2] The street name/number of the address. + * @param {string} [params.city] The city of the address for which the address proof is created. + * @param {string} [params.region] The region of the address for which the address proof is created. + * @param {string} [params.postal_code] The postal code of the address that is being created. + * @param {object} [params.file] A File to upload, which needs to be considered the proof of address. Max. file Size = 5 MB. File should be in jpg, pdf, or png format. + * @param {string} [params.subaccount] The link to the subaccount resource associated with the application. If the application belongs to the main account, this field will be null. + * @param {string} [params.fiscal_identification_code] The code is available for businesses alone and will be available for spain mobile numbers. If not present, return null. + * @param {string} [params.street_code] Street code of the address. Return null if not present. + * @param {string} [params.municipal_code] Municipal code of the address. + * @promise {object} return {@link Address} object + * @fail {Error} return Error + */ + + update(params) { + return super.update(params); + } + +/** + * delete Identity + * @method + * @promise {object} return true on success + * @fail {Error} return Error + */ + delete() { + return super.delete(); + } + +} +/** + * Represents a Identity interface + * @constructor + * @param {function} client - make api call + * @param {object} [data] - data of call + */ +export class IdentityInterface extends PlivoResourceInterface { + + constructor(client, data = {}) { + super(action, Identity, idField, client); + extend(this, data); + + this[clientKey] = client; + } + +/** + * get Identity by given id + * @method + * @param {string} id - id of Identity + * @promise {object} return {@link Identity} object + * @fail {Error} return Error + */ + get(id) { + return super.get(id); + } + +/** + * create Identity + * @method + * @param {string} country_iso Country ISO 2 code. + * @param {string} salutation This can have values: Mr, Ms. + * @param {string} first_name First name of the user for whom the identity is created. + * @param {string} last_name Second name of the user for whom the identity is created. + * @param {string} birth_place Birthplace of the user for whom the identity is created. + * @param {string} birth_date Birth date in yyyy-mm-dd format of the user for whom the identity is created. + * @param {string} nationality Nationality of the user for whom the identity is created. + * @param {string} id_nationality Nationality mentioned in the identity proof. + * @param {string} id_issue_date Issue date in yyyy-mm-dd mentioned in the identity proof. + * @param {string} id_type Building name/number. + * @param {string} id_number The unique number on the identifier. + * @param {string} address_line1 Building name/number. + * @param {string} address_line2 The street name/number of the address. + * @param {string} city The city of the address for which the address proof is created. + * @param {string} region The region of the address for which the address proof is created. + * @param {string} postal_code The postal code of the address that is being created. + * @param {object} params - to create Identity + * @param {string} [params.alias] Alias name of the Identity. + * @param {string} [params.business_name] Business name of the user for whom the identity is created. + * @param {string} [params.fiscal_identification_code] The code is valid for businesses alone. + * @param {string} [params.street_code] Street code of the address. + * @param {string} [params.municipal_code] Municipal code of the address. + * @param {string} [params.subaccount] The link to the subaccount resource associated with the application. If the application belongs to the main account, this field will be null. + * @param {object} [params.file] A File to upload, which needs to be considered the proof of address. Max. file Size = 5 MB. File should be in jpg, pdf, or png format. + * @promise {object} return {@link PlivoGenericResponse} object + * @fail {Error} return Error + */ + create( + country_iso, + salutation, + first_name, + last_name, + birth_place, + birth_date, + nationality, + id_nationality, + id_issue_date, + id_type, + id_number, + address_line1, + address_line2, + city, + region, + postal_code, + params = {}) { + + let errors = validate([ + {field: 'country_iso', value: country_iso, validators: ['isRequired', 'isString']}, + {field: 'salutation', value: salutation, validators: ['isRequired', 'isString']}, + {field: 'first_name', value: first_name, validators: ['isRequired', 'isString']}, + {field: 'last_name', value: last_name, validators: ['isRequired', 'isString']}, + {field: 'birth_place', value: birth_place, validators: ['isRequired', 'isString']}, + {field: 'birth_date', value: birth_date, validators: ['isRequired', 'isString']}, + {field: 'nationality', value: nationality, validators: ['isRequired', 'isString']}, + {field: 'id_nationality', value: id_nationality, validators: ['isRequired', 'isString']}, + {field: 'id_issue_date', value: id_issue_date, validators: ['isRequired', 'isString']}, + {field: 'id_type', value: id_type, validators: ['isRequired', 'isString']}, + {field: 'id_number', value: id_number, validators: ['isRequired', 'isString']}, + {field: 'address_line1', value: address_line1, validators: ['isRequired', 'isString']}, + {field: 'address_line2', value: address_line2, validators: ['isRequired', 'isString']}, + {field: 'city', value: city, validators: ['isRequired', 'isString']}, + {field: 'region', value: region, validators: ['isRequired', 'isString']}, + {field: 'postal_code', value: postal_code, validators: ['isRequired', 'isString']} + ]); + + if (errors) { + return errors; + } + + params.country_iso = country_iso; + params.salutation = salutation; + params.first_name = first_name; + params.last_name = last_name; + params.birth_place = birth_place; + params.birth_date = birth_date; + params.nationality = nationality; + params.id_nationality = id_nationality; + params.id_issue_date = id_issue_date; + params.id_type = id_type; + params.id_number = id_number; + params.address_line1 = address_line1; + params.address_line2 = address_line2; + params.city = city; + params.region = region; + params.postal_code = postal_code; + + return super.create(params); + } + +/** + * update Identity + * @method + * @param {string} id - id of Identity + * @param {object} params - to update Identity + * @param {string} [params.country_iso] Country ISO 2 code. + * @param {string} [params.alias] Alias name of the Identity. + * @param {string} [params.salutation] This can have values: Mr, Ms. + * @param {string} [params.first_name] First name of the user for whom the identity is created. + * @param {string} [params.last_name] Second name of the user for whom the identity is created. + * @param {string} [params.birth_place] Birthplace of the user for whom the identity is created. + * @param {string} [params.birth_date] Birth date in yyyy-mm-dd format of the user for whom the identity is created. + * @param {string} [params.nationality] Nationality of the user for whom the identity is created. + * @param {string} [params.id_nationality] Nationality mentioned in the identity proof. + * @param {string} [params.id_issue_date] Issue date in yyyy-mm-dd mentioned in the identity proof. + * @param {string} [params.business_name] Business name of the user for whom the identity is created. + * @param {string} [params.id_type] Building name/number. + * @param {string} [params.id_number] The unique number on the identifier. + * @param {string} [params.address_line1] Building name/number. + * @param {string} [params.address_line2] The street name/number of the address. + * @param {string} [params.city] The city of the address for which the address proof is created. + * @param {string} [params.region] The region of the address for which the address proof is created. + * @param {string} [params.postal_code] The postal code of the address that is being created. + * @param {object} [params.file] A File to upload, which needs to be considered the proof of address. Max. file Size = 5 MB. File should be in jpg, pdf, or png format. + * @param {string} [params.subaccount] The link to the subaccount resource associated with the application. If the application belongs to the main account, this field will be null. + * @param {string} [params.fiscal_identification_code] The code is available for businesses alone and will be available for spain mobile numbers. If not present, return null. + * @param {string} [params.street_code] Street code of the address. Return null if not present. + * @param {string} [params.municipal_code] Municipal code of the address. + * @promise {object} return {@link Identity} object + * @fail {Error} return Error + */ + update(id, params) { + let errors = validate([ + {field: 'id', value: id, validators: ['isRequired']} + ]); + + if (errors) { + return errors; + } + return new Identity(this[clientKey], { + id: id + }).update(params); + } + +/** + * delete Identity + * @method + * @param {string} id - id of Identity + * @promise {object} return true on success + * @fail {Error} return Error + */ + delete(id) { + return new Identity(this[clientKey], { + id: id + }).delete(); + } +} diff --git a/lib/resources/numbers.js b/lib/resources/numbers.js index f927bf7b..405303d9 100644 --- a/lib/resources/numbers.js +++ b/lib/resources/numbers.js @@ -27,13 +27,14 @@ export class PhoneNumber extends PlivoResource { * Buy Phone Number * @method * @param {string} appId - app id + * @param {object} [params.verification_info] - This contains the document associated with the phone number. It will contain: type - “address” or “identity”, id - Identifier of the “address” or “identity” object. * @promise {@link PlivoGenericResponse} return PlivoGenericResponse Object if success * @fail {Error} return Error */ - buy(appId) { + buy(appId, verification_info) { return new PhoneNumberInterface(this[clientKey], { id: this.id - }).buy(appId); + }).buy(appId, verification_info); } } @@ -56,14 +57,19 @@ export class PhoneNumberInterface extends PlivoResourceInterface { * Buy Phone Number * @method * @param {string} appId - app id + * @param {object} [params.verification_info] - This contains the document associated with the phone number. It will contain: type - “address” or “identity”, id - Identifier of the “address” or “identity” object. * @promise {@link PlivoGenericResponse} return PlivoGenericResponse Object if success * @fail {Error} return Error */ - buy(appId) { + buy(appId, verification_info) { let params = {}; if (appId) { params.app_id = appId; } + if (verification_info) { + params.verification_info = verification_info; + } + return super.create(params); } } @@ -101,6 +107,7 @@ export class NumberResource extends PlivoResource { * @param {string} [params.appId] - app id * @param {string} [params.subAccount] - auth_id of subaccount * @param {string} [params.alias] - textual name of number + * @param {object} [params.verification_info] - This contains the document associated with the phone number. It will contain: type - “address” or “identity”, id - Identifier of the “address” or “identity” object. * @promise {@link NumberResource} return NumberResource Object if success * @fail {Error} return Error */ @@ -203,6 +210,7 @@ export class NumberInterface extends PlivoResourceInterface { * @param {string} [params.appId] - app id * @param {string} [params.subAccount] - auth_id of subaccount * @param {string} [params.alias] - textual name of number + * @param {object} [params.verification_info] - This contains the document associated with the phone number. It will contain: type - “address” or “identity”, id - Identifier of the “address” or “identity” object. * @promise {@link NumberResource} return NumberResource Object if success * @fail {Error} return Error */ diff --git a/lib/rest/client-test.js b/lib/rest/client-test.js index b96a2ac0..7823cfb1 100644 --- a/lib/rest/client-test.js +++ b/lib/rest/client-test.js @@ -1,6 +1,8 @@ import {Request} from './request-test.js'; import {CallInterface} from '../resources/call.js'; import {AccountInterface, SubaccountInterface} from '../resources/accounts.js'; +import {AddressInterface} from "../resources/addresses"; +import {IdentityInterface} from "../resources/identities"; import {ApplicationInterface} from '../resources/applications.js'; import {ConferenceInterface} from '../resources/conferences.js'; import {EndpointInterface} from '../resources/endpoints.js'; @@ -41,6 +43,8 @@ export class Client { this.calls = new CallInterface(client); this.accounts = new AccountInterface(client); this.subAccounts = new SubaccountInterface(client); + this.addresses = new AddressInterface(client); + this.identities = new IdentityInterface(client); this.applications = new ApplicationInterface(client); this.conferences = new ConferenceInterface(client); this.endpoints = new EndpointInterface(client); diff --git a/lib/rest/client.js b/lib/rest/client.js index 894db589..a237b651 100644 --- a/lib/rest/client.js +++ b/lib/rest/client.js @@ -3,6 +3,8 @@ import {camelCaseRequestWrapper} from './utils'; import {name, version} from '../../package.json'; import {CallInterface} from "../resources/call"; import {SubaccountInterface, AccountInterface} from "../resources/accounts"; +import {AddressInterface} from "../resources/addresses"; +import {IdentityInterface} from "../resources/identities"; import {ApplicationInterface} from "../resources/applications"; import {ConferenceInterface} from "../resources/conferences"; import {EndpointInterface} from "../resources/endpoints"; @@ -55,6 +57,8 @@ export class Client { this.accounts = new AccountInterface(client); this.subaccounts = this.subAccounts = new SubaccountInterface(client); this.applications = new ApplicationInterface(client); + this.addresses = new AddressInterface(client); + this.identities = new IdentityInterface(client); this.conferences = new ConferenceInterface(client); this.endpoints = new EndpointInterface(client); this.messages = new MessageInterface(client); diff --git a/lib/rest/request-test.js b/lib/rest/request-test.js index 057e0bb6..3cec59f2 100644 --- a/lib/rest/request-test.js +++ b/lib/rest/request-test.js @@ -1072,6 +1072,215 @@ export function Request(config) { }); } + // ============= Address =================== + + if (action == 'Verification/Address/1/' && method == 'GET') { + resolve({ + response: {}, + body: { + "account": "MAXXXXXXXXXXXXXXXXXX", + "address_line1": "128", + "address_line2": "RUE DU COMMANDANT GUILBAUD", + "alias": "test_address", + "api_id": "08361d92-0b59-11e8-aa7e-02ad5072be3e", + "city": "PARIS", + "country_iso": "FR", + "document_details": { + "address_line1": "128", + "address_line2": "RUE DU COMMANDANT GUILBAUD", + "city": "PARIS", + "first_name": "Bruce", + "last_name": "Wayne", + "postal_code": "75016", + "region": "PARIS", + "salutation": "Mr" + }, + "first_name": "Bruce", + "id": 1, + "last_name": "Wayne", + "postal_code": "75016", + "region": "PARIS", + "salutation": "Mr", + "subaccount": null, + "url": "https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/Verification/Address/20220771838737/", + "validation_status": "accepted", + "verification_status": "pending" + } + }); + } + if (action == 'Verification/Address/' && method == 'GET') { + resolve({ + response: {}, + body: { + "api_id": "af8b199a-0b58-11e8-b939-06755d68f0ca", + "meta": { + "limit": 1, + "next": "https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/Verification/Address/?limit=1&offset=1", + "offset": 0, + "previous": null, + "total_count": 19 + }, + "objects": [ + { + "account": "MAXXXXXXXXXXXXXXXXXX", + "address_line1": "128", + "address_line2": "RUE DU COMMANDANT GUILBAUD", + "alias": "test_address", + "city": "PARIS", + "country_iso": "FR", + "document_details": { + "address_line1": "128", + "address_line2": "RUE DU COMMANDANT GUILBAUD", + "city": "PARIS", + "first_name": "Bruce", + "last_name": "Wayne", + "postal_code": "75016", + "region": "PARIS", + "salutation": "Mr" + }, + "first_name": "Bruce", + "id": "20220771838737", + "last_name": "Wayne", + "postal_code": "75016", + "region": "PARIS", + "salutation": "Mr", + "subaccount": null, + "url": "https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/Verification/Address/20220771838737/", + "validation_status": "accepted", + "verification_status": "pending" + } + ] + } + }); + } + if (action == 'Verification/Address/1/' && method == 'POST') { + resolve({ + response: {}, + body: { + "message": "Your request has been accepted.", + "api_id": "5a9fcb68-523d-11e1-86da-6ff39efcb949" + } + }); + } + if (action == 'Verification/Address/' && method == 'POST') { + resolve({ + response: {}, + body: { + "api_id": "324a7dd8-0db2-11e4-8a4a-123140008edf", + "message": "Your request has been accepted." + } + }); + } + + if (action == 'Verification/Address/1/' && method == 'DELETE') { + resolve({ + response: {}, + body: { + } + }); + } + + // ============= Identity =================== + + if (action == 'Verification/Identity/1/' && method == 'GET') { + resolve({ + response: {}, + body: { + "account": "MAXXXXXXXXXXXXXXXXXX", + "alias": null, + "api_id": "6e951a10-0b5a-11e8-a416-06f8d2f9b24c", + "country_iso": "FR", + "document_details": { + "first_name": "Bruce", + "id_number": "33522", + "id_type": "passport", + "last_name": "Wayne", + "nationality": "FR", + "salutation": "Mr" + }, + "first_name": "Bruce", + "id": "1", + "id_number": "33522", + "id_type": "passport", + "last_name": "Wayne", + "nationality": "FR", + "salutation": "Mr", + "subaccount": null, + "url": "https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/Verification/Identity/24856289978366/", + "validation_status": "pending", + "verification_status": "pending" + } + }); + } + if (action == 'Verification/Identity/' && method == 'GET') { + resolve({ + response: {}, + body: { + "api_id": "3c294e0c-0b5a-11e8-9ad8-064c8d7b2d26", + "meta": { + "limit": 1, + "next": "https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/Verification/Identity/?limit=1&offset=1", + "offset": 0, + "previous": null, + "total_count": 19 + }, + "objects": [ + { + "account": "MAXXXXXXXXXXXXXXXXXX", + "alias": null, + "country_iso": "FR", + "document_details": { + "first_name": "Bruce", + "id_number": "33522", + "id_type": "passport", + "last_name": "Wayne", + "nationality": "FR", + "salutation": "Mr" + }, + "first_name": "Bruce", + "id": "24856289978366", + "id_number": "33522", + "id_type": "passport", + "last_name": "Wayne", + "nationality": "FR", + "salutation": "Mr", + "subaccount": null, + "url": "https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/Verification/Identity/24856289978366/", + "validation_status": "pending", + "verification_status": "pending" + } + ] + } + }); + } + if (action == 'Verification/Identity/1/' && method == 'POST') { + resolve({ + response: {}, + body: { + "message": "Your request has been accepted.", + "api_id": "5a9fcb68-523d-11e1-86da-6ff39efcb949" + } + }); + } + if (action == 'Verification/Identity/' && method == 'POST') { + resolve({ + response: {}, + body: { + "api_id": "324a7dd8-0db2-11e4-8a4a-123140008edf", + "message": "Your request has been accepted." + } + }); + } + + if (action == 'Verification/Identity/1/' && method == 'DELETE') { + resolve({ + response: {}, + body: { + } + }); + } + + reject(new Error('not found')); }); }; diff --git a/lib/rest/utils.js b/lib/rest/utils.js index 81f4cf3b..445e5617 100644 --- a/lib/rest/utils.js +++ b/lib/rest/utils.js @@ -3,8 +3,15 @@ import _snakeCase from 'lodash/snakeCase'; import _mapKeys from 'lodash/mapKeys'; import _mapValues from 'lodash/mapValues'; import _map from 'lodash/map'; +import _includes from 'lodash/includes'; + +const whiteListed = ['address_line1', 'address_line2'] function recursivelyRenameObject(object, renameFunc) { + if (object && typeof object.on === 'function') { + return object; + } + if (!(object instanceof Object)) { return object; } @@ -22,6 +29,9 @@ export function camelCaseRequestWrapper(requestFunc) { return (method, action, params) => { params = recursivelyRenameObject(params, function (value, key) { + if (_includes(whiteListed, key)) { + return key; + } if(typeof key !== 'string') return key; return _snakeCase(key) diff --git a/lib/utils/security.js b/lib/utils/security.js index f5a6950b..ac27bfc4 100644 --- a/lib/utils/security.js +++ b/lib/utils/security.js @@ -17,15 +17,20 @@ export function verifyOldSignature(authId: string, uri: string, params: {[string } export function validateSignature(uri: string, nonce: string, signature: string, auth_token: string) { + let authentication_string = generateSignature(uri, nonce, signature, auth_token); + return authentication_string == signature; +} + +export function generateSignature(uri: string, nonce: string, signature: string, auth_token: string) { nonce = utf8.encode(nonce); signature = utf8.encode(signature); auth_token = utf8.encode(auth_token); uri = utf8.encode(uri); let parsed_uri = parser.parse(uri); let url_protocol = parsed_uri.protocol == '' ? 'http://' : parsed_uri.protocol+'://'; - let base_url = buildUrl(url_protocol+parsed_uri.host, { path: parsed_uri.path }); + let url_port = ( parsed_uri.port ? ':' + parsed_uri.port : ''); + let base_url = buildUrl(url_protocol + parsed_uri.host + url_port, { path: parsed_uri.path }); let hmac = crypto.createHmac('sha256', auth_token); let hmacBytes = base64.decode(hmac.update(base_url+nonce).digest('base64')); - let authentication_string = base64.encode(hmacBytes); - return authentication_string == signature; + return base64.encode(hmacBytes); } diff --git a/package.json b/package.json index 761d2afa..c96d943c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "plivo", - "version": "4.0.0", + "version": "4.1.0", "description": "A Node.js SDK to make voice calls & send SMS using Plivo and to generate Plivo XML", "homepage": "https://github.com/plivo/plivo-node", "files": [ diff --git a/test/addresses.js b/test/addresses.js new file mode 100644 index 00000000..5a5d0050 --- /dev/null +++ b/test/addresses.js @@ -0,0 +1,83 @@ +import assert from 'assert'; +import sinon from 'sinon'; +import {Client} from '../lib/rest/client-test'; +import {PlivoGenericResponse} from '../lib/base.js'; + +let client = new Client('sampleid', 'sammpletoken', 'sampleproxy'); + +describe('Identity', function () { + it('should get Identity', function () { + return client.identities.get(1) + .then(function(identity) { + assert.equal(identity.id, 1) + }) + }); + + it('list identities', function () { + return client.identities.list() + .then(function(identities) { + assert.equal(identities.length, 1) + }) + }); + + it('has meta information', function () { + return client.identities.list() + .then(function(identities) { + assert.equal(identities.meta.totalCount, 19) + }) + }); + + it('should throw error - country_iso is required via interface', function () { + return client.identities.create(null, "Mr", "first_name", "last_name", "birth_place", "1984-12-12", "nationality", "id_nationality", "1999-12-12", "id_type", "id_number", "address_line1", "address_line2", "city", "Region", "Postal Code") + .catch(function(error){ + assert.equal(error.message, 'Missing mandatory field: country_iso, country_iso should be string.') + }) + }); + + it('should create identity via interface', function () { + return client.identities.create("US", "Mr", "first_name", "last_name", "birth_place", "1984-12-12", "nationality", "id_nationality", "1999-12-12", "id_type", "id_number", "address_line1", "address_line2", "city", "Region", "Postal Code") + .then(function(identity){ + assert.equal(identity.message, 'Your request has been accepted.') + }) + }); + + it('should update Identity via interface', function () { + return client.identities.update(1) + .then(function(identity) { + assert.equal(identity.message, 'Your request has been accepted.') + }) + }); + + it('should throw error - id is required via interface', function () { + return client.identities.update(null, {}) + .catch(function(err){ + assert.equal(err.message, 'Missing mandatory field: id') + }) + }); + + it('should update Identity', function () { + return client.identities.get(1) + .then(function(identity) { + return identity.update({answer_url: 'answerUrl'}) + }) + .then(function(identity){ + assert.equal(identity.answer_url, 'answerUrl') + }) + }); + + it('delete identity', function () { + return client.identities.get(1) + .then(function(identity){ + return identity.delete() + }) + .then(function(status) { + assert.equal(status, true) + }) + }); + it('delete identity via interface', function () { + return client.identities.delete(1) + .then(function(status) { + assert.equal(status, true) + }) + }); +}); diff --git a/test/identities.js b/test/identities.js new file mode 100644 index 00000000..ff6292ec --- /dev/null +++ b/test/identities.js @@ -0,0 +1,83 @@ +import assert from 'assert'; +import sinon from 'sinon'; +import {Client} from '../lib/rest/client-test'; +import {PlivoGenericResponse} from '../lib/base.js'; + +let client = new Client('sampleid', 'sammpletoken', 'sampleproxy'); + +describe('Address', function () { + it('should get Address', function () { + return client.addresses.get(1) + .then(function(address) { + assert.equal(address.id, 1) + }) + }); + + it('list addresses', function () { + return client.addresses.list() + .then(function(addresses) { + assert.equal(addresses.length, 1) + }) + }); + + it('has meta information', function () { + return client.addresses.list() + .then(function(addresses) { + assert.equal(addresses.meta.totalCount, 19) + }) + }); + + it('should throw error - country_iso is required via interface', function () { + return client.addresses.create(null, "Mr", "first_name", "last_name", "address_line1", "address_line2", "New York", "Region", "Postal Code", "nation_id") + .catch(function(error){ + assert.equal(error.message, 'Missing mandatory field: country_iso, country_iso should be string.') + }) + }); + + it('should create address via interface', function () { + return client.addresses.create("en-US", "Mr", "first_name", "last_name", "address_line1", "address_line2", "New York", "Region", "Postal Code", "nation_id") + .then(function(address){ + assert.equal(address.message, 'Your request has been accepted.') + }) + }); + + it('should update Address via interface', function () { + return client.addresses.update(1) + .then(function(address) { + assert.equal(address.message, 'Your request has been accepted.') + }) + }); + + it('should throw error - id is required via interface', function () { + return client.addresses.update(null, {}) + .catch(function(err){ + assert.equal(err.message, 'Missing mandatory field: id') + }) + }); + + it('should update Address', function () { + return client.addresses.get(1) + .then(function(address) { + return address.update({answer_url: 'answerUrl'}) + }) + .then(function(address){ + assert.equal(address.answer_url, 'answerUrl') + }) + }); + + it('delete address', function () { + return client.addresses.get(1) + .then(function(address){ + return address.delete() + }) + .then(function(status) { + assert.equal(status, true) + }) + }); + it('delete address via interface', function () { + return client.addresses.delete(1) + .then(function(status) { + assert.equal(status, true) + }) + }); +}); diff --git a/test/utils.js b/test/utils.js index 5c03e0c2..5a0aca27 100644 --- a/test/utils.js +++ b/test/utils.js @@ -37,4 +37,16 @@ describe('Security', function () { false ); }); + + it('should generate url with port', function () { + var validate = validateSignature('https://answer.url:8080','123456','xeV6S6BPIQJ/rgKCjCm/Fo2ve5zNe1fatQoHyRT8vxQ=','my_auth_tokens') + assert.equal(validate, true); + }); + + it('should fail for url with port', function () { + assert.equal( + validateSignature('https://answer.url:8080','12345','ehV3IKhLysWBxC1sy8INm0qGoQYdYsHwuoKjsX7FsXc=','my_auth_token'), + false + ); + }); });