Skip to content

Commit

Permalink
Merge pull request #44 from inloco/integ/4.1.0
Browse files Browse the repository at this point in the history
release/4.1.0
  • Loading branch information
marcelscr authored Jul 20, 2022
2 parents 39d77ea + d0c59b4 commit b5a8b79
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 12 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The official Node.js library for integrating with the Incognia API.

Documentation can be found at <https://us.incognia.com>
Documentation can be found at <https://developer.incognia.com/docs>

## Installation

Expand Down Expand Up @@ -147,6 +147,20 @@ try {
}
```

### Searching for accounts

This method fetches every account associated with a specific installation, returning the number of accounts and an array containing the account IDs and related timestamps. Use this API to map the relationship between user accounts and devices.

```js
try {
const accounts = await incogniaApi.searchAccounts({
installationId: 'installation_id'
})
} catch (error) {
console.log(error.message)
}
```

## Typescript enabled

Thanks to Typescript, all methods attributes and data response are typed, meaning any typescript-enabled editor can take advantage of intellisense and auto-complete:
Expand Down Expand Up @@ -193,4 +207,4 @@ try {

## More documentation

More documentation and code examples can be found at <https://us.incognia.com>
More documentation and code examples can be found at <https://developer.incognia.com/docs>
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@incognia/api",
"author": "Incognia (https://us.incognia.com)",
"repository": "https://github.com/inloco/incognia-node",
"version": "4.0.1",
"version": "4.1.0",
"license": "MIT",
"main": "dist/index.js",
"module": "dist/api.esm.js",
Expand All @@ -15,11 +15,12 @@
"node": ">=12"
},
"scripts": {
"start": "dts watch",
"build": "dts build",
"start": "yarn genVersion && dts watch",
"build": "yarn genVersion && dts build",
"test": "dts test",
"lint": "dts lint",
"prepare": "dts build"
"prepare": "yarn build",
"genVersion": "genversion --es6 src/version.ts"
},
"peerDependencies": {},
"husky": {
Expand All @@ -38,6 +39,7 @@
"@tsconfig/recommended": "^1.0.1",
"@types/qs": "^6.9.7",
"dts-cli": "^0.19.4",
"genversion": "^3.1.1",
"husky": "^7.0.4",
"nock": "^13.1.4",
"tslib": "^2.3.1",
Expand Down
30 changes: 27 additions & 3 deletions src/incogniaApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
IncogniaError,
CustomRequestError
} from './errors'
import { buildUserAgent } from './utils'

import {
TransactionType,
Expand All @@ -21,7 +22,9 @@ import {
SignupResponse,
Method,
RegisterSignupProps,
RegisterTransactionProps
RegisterTransactionProps,
SearchAccountsBodyProps,
SearchAccountsResponse
} from './types'

type IncogniaApiConstructor = {
Expand All @@ -41,6 +44,7 @@ type ApiEndpoints = {
SIGNUPS: string
TRANSACTIONS: string
FEEDBACKS: string
ACCOUNTS: string
}

const BASE_ENDPOINT = 'https://api.incognia.com/api'
Expand All @@ -49,7 +53,8 @@ export const apiEndpoints: ApiEndpoints = {
TOKEN: `${BASE_ENDPOINT}/v2/token`,
SIGNUPS: `${BASE_ENDPOINT}/v2/onboarding/signups`,
TRANSACTIONS: `${BASE_ENDPOINT}/v2/authentication/transactions`,
FEEDBACKS: `${BASE_ENDPOINT}/v2/feedbacks`
FEEDBACKS: `${BASE_ENDPOINT}/v2/feedbacks`,
ACCOUNTS: `${BASE_ENDPOINT}/v2/accounts/search`
}

export class IncogniaApi {
Expand Down Expand Up @@ -142,13 +147,31 @@ export class IncogniaApi {
})
}

// Search Accounts
async searchAccounts(
props: SearchAccountsBodyProps
): Promise<SearchAccountsResponse> {
const { installationId } = props || {}
if (!installationId) {
throw new IncogniaError('No installationId provided')
}
const data = convertObjectToSnakeCase(props)

return this.resourceRequest({
url: apiEndpoints.ACCOUNTS,
method: Method.Post,
data
})
}

async resourceRequest(options: AxiosRequestConfig) {
await this.updateAccessToken()
try {
const response = await axios({
...options,
headers: {
'Content-Type': 'application/json',
'User-Agent': buildUserAgent(),
Authorization: `${this.incogniaToken?.tokenType} ${this.incogniaToken?.accessToken}`
}
})
Expand Down Expand Up @@ -200,7 +223,8 @@ export class IncogniaApi {
password: this.clientSecret
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': buildUserAgent()
}
})
} catch (e: unknown) {
Expand Down
29 changes: 29 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type SignupResponse = {
id: string
requestId: string
riskAssessment: RiskAssessment
reasons: Array<Reason>
evidence: SignupEvidenceSummary
}

Expand All @@ -40,9 +41,15 @@ export type RegisterPaymentProps = RegisterLoginProps & {
export type TransactionResponse = {
id: string
riskAssessment: RiskAssessment
reasons: Array<Reason>
evidence: TransactionEvidenceSummary
}

type Reason = {
code: string
source: string
}

export type RegisterFeedbackBodyProps = {
accountId?: string
appId?: string
Expand Down Expand Up @@ -185,6 +192,11 @@ type SignupEvidenceSummary = {
locationEventsNearAddress: number
locationEventsQuantity: number
locationServices: LocationServices
accessedAccounts: number
appReinstallations: number
differentDeclaredAddresses: number
distanceFromNearestLocationToDeclaredAddress: number
distanceFromLastLocationToDeclaredAddress: number
}

type TransactionEvidenceSummary = {
Expand All @@ -199,6 +211,8 @@ type TransactionEvidenceSummary = {
locationEventsQuantity: number
locationServices: LocationServices
sensorMatchType: SensorMatchType
accessedAccounts: number
appReinstallations: number
}

type TransactionAddress = {
Expand Down Expand Up @@ -255,3 +269,18 @@ export enum FeedbackEvent {
AccountTakeover = 'account_takeover',
MposFraud = 'mpos_fraud'
}

export type SearchAccountsBodyProps = {
installationId: string
}

export type SearchAccountsResponse = {
count: number
data: Array<AccountData>
}

type AccountData = {
accountId: string
firstEventAt: string
lastEventAt: string
}
13 changes: 13 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import os from 'os'
import { version } from './version'

export const buildUserAgent = () => {
const platform = os.platform()
const platformVersion = os.release()
const platformArch = os.arch()

const nodeVersion = process.version

// Example: incognia-node/4.0.1 (darwin 21.2.0 x64) Node/v16.15.1
return `incognia-node/${version} (${platform} ${platformVersion} ${platformArch}) Node/${nodeVersion}`
}
2 changes: 2 additions & 0 deletions src/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Generated by genversion.
export const version = '4.1.0'
45 changes: 45 additions & 0 deletions test/incogniaApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,51 @@ describe('API', () => {
})
})
})

it('retrieves accounts', async () => {
const timestamp = '2022-06-02T22:25:30.885104Z'

const apiResponse = {
count: 2,
data: [
{
account_id: '1',
first_event_at: timestamp,
last_event_at: timestamp
},
{
account_id: '2',
first_event_at: timestamp,
last_event_at: timestamp
}
]
}

const expectedResponse = {
count: 2,
data: [
{
accountId: '1',
firstEventAt: timestamp,
lastEventAt: timestamp
},
{
accountId: '2',
firstEventAt: timestamp,
lastEventAt: timestamp
}
]
}

nock(BASE_ENDPOINT_URL)
.post(`/v2/accounts/search`)
.reply(200, apiResponse)

const accounts = await incogniaApi.searchAccounts({
installationId: 'installation_id'
})
expect(accounts).toEqual(expectedResponse)
})
})

describe('Access token managament', () => {
Expand Down
38 changes: 35 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2001,6 +2001,11 @@ commander@^2.20.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==

commander@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==

commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
Expand Down Expand Up @@ -2720,6 +2725,13 @@ find-cache-dir@^3.3.1:
make-dir "^3.0.2"
pkg-dir "^4.1.0"

find-package@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/find-package/-/find-package-1.0.0.tgz#d7738da67e3c5f055c24d3e19aa1aeed063c3e83"
integrity sha512-yVn71XCCaNgxz58ERTl8nA/8YYtIQDY9mHSrgFBfiFtdNNfY0h183Vh8BRkKxD8x9TUw3ec290uJKhDVxqGZBw==
dependencies:
parents "^1.0.1"

find-up@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
Expand Down Expand Up @@ -2805,6 +2817,14 @@ gensync@^1.0.0-beta.2:
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==

genversion@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/genversion/-/genversion-3.1.1.tgz#5da18c1ea21813b560f923b37dbbb0df528b7c06"
integrity sha512-/H861PMsihhjgX2qqhTN8egM11V04imhA+3JRFY3jjPua2Sy1NqaqqQPjSP8rdM9jZoKpFhVj9g3Fs9XPCjBYQ==
dependencies:
commander "^7.2.0"
find-package "^1.0.0"

get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
Expand Down Expand Up @@ -4034,9 +4054,9 @@ minimatch@^3.0.4:
brace-expansion "^1.1.7"

minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
version "1.2.6"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==

mri@^1.1.0:
version "1.2.0"
Expand Down Expand Up @@ -4283,6 +4303,13 @@ parent-module@^1.0.0:
dependencies:
callsites "^3.0.0"

parents@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751"
integrity sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==
dependencies:
path-platform "~0.11.15"

parse-json@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
Expand Down Expand Up @@ -4331,6 +4358,11 @@ path-parse@^1.0.6, path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==

path-platform@~0.11.15:
version "0.11.15"
resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2"
integrity sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==

path-type@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
Expand Down

0 comments on commit b5a8b79

Please sign in to comment.