@rebilly/risk-data-collector 2.2.1 → 2.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebilly/risk-data-collector",
3
- "version": "2.2.1",
3
+ "version": "2.4.0",
4
4
  "description": "Microlibrary that collects browser data for risk assessment",
5
5
  "type": "module",
6
6
  "main": "dist/data-collector.js",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "https://github.com/Rebilly/risk-data-collector"
19
+ "url": "https://github.com/Rebilly/rebilly"
20
20
  },
21
21
  "keywords": [
22
22
  "rebilly",
@@ -25,9 +25,13 @@
25
25
  "3ds2",
26
26
  "payment"
27
27
  ],
28
+ "files": [
29
+ "dist",
30
+ "CHANGELOG.md"
31
+ ],
28
32
  "dependencies": {
29
33
  "@babel/runtime": "^7.10.1",
30
- "@fingerprintjs/fingerprintjs": "^2.1.0"
34
+ "@fingerprintjs/fingerprintjs": "^3.3.3"
31
35
  },
32
36
  "devDependencies": {
33
37
  "@babel/core": "^7.10.1",
package/.babelrc.json DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "presets": ["@babel/preset-env"],
3
- "plugins": ["@babel/plugin-transform-runtime"]
4
- }
5
-
package/.browserslistrc DELETED
@@ -1,3 +0,0 @@
1
- > 1%
2
- last 2 versions
3
- ie >= 11
package/.eslintrc.json DELETED
@@ -1,21 +0,0 @@
1
- {
2
- "env": {
3
- "browser": true,
4
- "es6": true
5
- },
6
- "extends": [
7
- "airbnb-base"
8
- ],
9
- "globals": {
10
- "Atomics": "readonly",
11
- "SharedArrayBuffer": "readonly"
12
- },
13
- "parserOptions": {
14
- "ecmaVersion": 2018,
15
- "sourceType": "module"
16
- },
17
- "rules": {
18
- "no-restricted-globals": "off",
19
- "import/prefer-default-export": "off"
20
- }
21
- }
@@ -1,18 +0,0 @@
1
- name: Build
2
-
3
- on: pull_request
4
-
5
- jobs:
6
- build-package:
7
- runs-on: ubuntu-latest
8
- name: Test and build package
9
- steps:
10
- - uses: actions/checkout@v2
11
- - name: Setup node
12
- uses: actions/setup-node@v1
13
- with:
14
- node-version: 12
15
- - run: yarn install --frozen-lockfile --non-interactive
16
- - run: yarn lint
17
- - run: yarn test
18
- - run: yarn build
@@ -1,21 +0,0 @@
1
- name: Publish
2
-
3
- on:
4
- release:
5
- types: [published]
6
-
7
- jobs:
8
- build-and-publish:
9
- runs-on: ubuntu-latest
10
- name: Build and publish on npm
11
- steps:
12
- - uses: actions/checkout@v2
13
- - uses: actions/setup-node@v1
14
- with:
15
- node-version: 12
16
- registry-url: https://registry.npmjs.org/
17
- - run: yarn install --frozen-lockfile --non-interactive
18
- - run: yarn build
19
- - run: npm publish --access public
20
- env:
21
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,140 +0,0 @@
1
- /* eslint-disable no-self-compare, no-undef, no-confusing-arrow */
2
- import { collectData, collectDataHelper } from '../../src/data-collector';
3
- import getFingerprint from '../../src/fingerprint';
4
- import getFraudSessionId from '../../src/kount';
5
- import {
6
- dataWithAllArguments,
7
- dataMissingScreen,
8
- dataMissingNavigator,
9
- dataMissingFingerprintJs,
10
- dataMissingKount,
11
- dataMissingAllArguments,
12
- } from '../test-data';
13
-
14
- const isNull = (x) => !x && typeof x === 'object';
15
- const getType = (value) => isNull(value) ? null : typeof value;
16
-
17
- const getTypes = (data) => {
18
- const dataTypes = {};
19
-
20
- Object.entries(data)
21
- .forEach(([key, value]) => {
22
- if (!isNull(value) && typeof value === 'object') {
23
- dataTypes[key] = getTypes(value);
24
- } else {
25
- dataTypes[key] = getType(value);
26
- }
27
- });
28
-
29
- return dataTypes;
30
- };
31
-
32
- const env = 'sandbox';
33
- const kountAccountId = '700000';
34
-
35
- describe('collectData', () => {
36
- it('Returns an object', async () => {
37
- const browserData = await collectData({ env, kountAccountId });
38
-
39
- expect(browserData).to.be.a('object');
40
- });
41
-
42
- it('Works when Kount configurations are omitted', async () => {
43
- const browserData = await collectData();
44
-
45
- expect(browserData).to.be.a('object');
46
- expect(getTypes(browserData)).to.deep.equal(dataMissingKount);
47
- });
48
-
49
- it('browserData has the correct property types', async () => {
50
- const browserData = getTypes(await collectData({ env, kountAccountId }));
51
-
52
- expect(browserData).to.deep.equal(dataWithAllArguments);
53
- });
54
- });
55
-
56
- describe('collectDataHelper', () => {
57
- it('Returns an object when it receives all arguments', async () => {
58
- const browserData = await collectDataHelper({
59
- env,
60
- screen,
61
- navigator,
62
- kountAccountId,
63
- getFingerprint,
64
- getFraudSessionId,
65
- });
66
-
67
- expect(browserData).to.be.a('object');
68
- });
69
-
70
- it('Uses fallback values whenever screen is missing', async () => {
71
- const browserData = getTypes(await collectDataHelper({
72
- env,
73
- screen: null,
74
- navigator,
75
- kountAccountId,
76
- getFingerprint,
77
- getFraudSessionId,
78
- }));
79
-
80
- expect(browserData).to.deep.equal(dataMissingScreen);
81
- });
82
-
83
- it('Uses fallback values whenever navigator is missing', async () => {
84
- const browserData = getTypes(await collectDataHelper({
85
- env,
86
- screen,
87
- navigator: null,
88
- kountAccountId,
89
- getFingerprint,
90
- getFraudSessionId,
91
- }));
92
-
93
- expect(browserData).to.deep.equal(dataMissingNavigator);
94
- });
95
-
96
- it('Uses fallback values whenever fingerprinterjs2 fails', async () => {
97
- const mockFingerprint = () => new Promise((resolve) => {
98
- resolve('');
99
- });
100
-
101
- const browserData = getTypes(await collectDataHelper({
102
- env,
103
- screen,
104
- navigator,
105
- kountAccountId,
106
- getFingerprint: mockFingerprint,
107
- getFraudSessionId,
108
- }));
109
-
110
- expect(browserData).to.deep.equal(dataMissingFingerprintJs);
111
- });
112
-
113
- it('Uses fallback values whenever Kount fails', async () => {
114
- const mockKount = () => new Promise((resolve) => {
115
- resolve('');
116
- });
117
-
118
- const browserData = getTypes(await collectDataHelper({
119
- env,
120
- screen,
121
- navigator,
122
- kountAccountId,
123
- getFingerprint,
124
- getFraudSessionId: mockKount,
125
- }));
126
-
127
- expect(browserData).to.deep.equal(dataMissingKount);
128
- });
129
-
130
- it('Uses fallback values if all arguments are missing', async () => {
131
- const browserData = getTypes(await collectDataHelper({
132
- screen: null,
133
- navigator: null,
134
- getFingerprint: null,
135
- getFraudSessionId: null,
136
- }));
137
-
138
- expect(browserData).to.deep.equal(dataMissingAllArguments);
139
- });
140
- });
@@ -1,110 +0,0 @@
1
- const dataWithAllArguments = {
2
- riskMetadata: {
3
- fingerprint: 'string',
4
- extraData: {
5
- kountFraudSessionId: 'string',
6
- },
7
- browserData: {
8
- colorDepth: 'number',
9
- isJavaEnabled: 'boolean',
10
- language: 'string',
11
- screenHeight: 'number',
12
- screenWidth: 'number',
13
- timeZoneOffset: 'number',
14
- },
15
- },
16
- };
17
-
18
- const dataMissingScreen = {
19
- riskMetadata: {
20
- fingerprint: 'string',
21
- extraData: {
22
- kountFraudSessionId: 'string',
23
- },
24
- browserData: {
25
- colorDepth: null,
26
- isJavaEnabled: 'boolean',
27
- language: 'string',
28
- screenHeight: null,
29
- screenWidth: null,
30
- timeZoneOffset: 'number',
31
- },
32
- },
33
- };
34
-
35
- const dataMissingNavigator = {
36
- riskMetadata: {
37
- fingerprint: 'string',
38
- extraData: {
39
- kountFraudSessionId: 'string',
40
- },
41
- browserData: {
42
- colorDepth: 'number',
43
- isJavaEnabled: null,
44
- language: null,
45
- screenHeight: 'number',
46
- screenWidth: 'number',
47
- timeZoneOffset: 'number',
48
- },
49
- },
50
- };
51
-
52
- const dataMissingFingerprintJs = {
53
- riskMetadata: {
54
- fingerprint: null,
55
- extraData: {
56
- kountFraudSessionId: 'string',
57
- },
58
- browserData: {
59
- colorDepth: 'number',
60
- isJavaEnabled: 'boolean',
61
- language: 'string',
62
- screenHeight: 'number',
63
- screenWidth: 'number',
64
- timeZoneOffset: 'number',
65
- },
66
- },
67
- };
68
-
69
- const dataMissingKount = {
70
- riskMetadata: {
71
- fingerprint: 'string',
72
- extraData: {
73
- kountFraudSessionId: null,
74
- },
75
- browserData: {
76
- colorDepth: 'number',
77
- isJavaEnabled: 'boolean',
78
- language: 'string',
79
- screenHeight: 'number',
80
- screenWidth: 'number',
81
- timeZoneOffset: 'number',
82
- },
83
- },
84
- };
85
-
86
- const dataMissingAllArguments = {
87
- riskMetadata: {
88
- fingerprint: null,
89
- extraData: {
90
- kountFraudSessionId: null,
91
- },
92
- browserData: {
93
- colorDepth: null,
94
- isJavaEnabled: null,
95
- language: null,
96
- screenHeight: null,
97
- screenWidth: null,
98
- timeZoneOffset: 'number',
99
- },
100
- },
101
- };
102
-
103
- export {
104
- dataWithAllArguments,
105
- dataMissingScreen,
106
- dataMissingNavigator,
107
- dataMissingFingerprintJs,
108
- dataMissingKount,
109
- dataMissingAllArguments,
110
- };
package/cypress.json DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "video": false,
3
- "fixturesFolder": false,
4
- "pluginsFile": false,
5
- "supportFile": false
6
- }
package/rollup.config.js DELETED
@@ -1,27 +0,0 @@
1
- import babel from '@rollup/plugin-babel';
2
- import resolve from '@rollup/plugin-node-resolve';
3
- import commonjs from '@rollup/plugin-commonjs';
4
- import { terser } from 'rollup-plugin-terser';
5
-
6
-
7
- export default {
8
- input: 'src/data-collector.js',
9
- output: [
10
- {
11
- file: 'dist/data-collector.min.js',
12
- format: 'iife',
13
- name: 'RiskDataCollector',
14
- sourcemap: true,
15
- },
16
- {
17
- file: 'dist/data-collector.js',
18
- format: 'es',
19
- },
20
- ],
21
- plugins: [
22
- resolve(),
23
- commonjs(),
24
- babel({ babelHelpers: 'runtime', skipPreflightCheck: true }),
25
- terser(),
26
- ],
27
- };
@@ -1,72 +0,0 @@
1
- /* eslint-disable no-console */
2
- import fingerprinter from './fingerprint';
3
- import kount from './kount';
4
-
5
- async function collectDataHelper({
6
- env = null,
7
- screen,
8
- navigator,
9
- kountAccountId = null,
10
- kountSessionId = null,
11
- getFingerprint,
12
- getFraudSessionId,
13
- }) {
14
- const {
15
- colorDepth,
16
- height: screenHeight,
17
- width: screenWidth,
18
- } = screen || {};
19
- const {
20
- javaEnabled,
21
- language,
22
- } = navigator || {};
23
- let fingerprint;
24
- let kountFraudSessionId;
25
-
26
- try {
27
- fingerprint = await getFingerprint();
28
-
29
- if (kountAccountId) {
30
- kountFraudSessionId = await getFraudSessionId({ env, kountAccountId, kountSessionId });
31
- }
32
- } catch (e) {
33
- console.error(e);
34
- }
35
-
36
- const data = {
37
- riskMetadata: {
38
- fingerprint: fingerprint || null,
39
- extraData: {
40
- kountFraudSessionId: kountFraudSessionId || null,
41
- },
42
- browserData: {
43
- colorDepth: colorDepth || null,
44
- isJavaEnabled: javaEnabled ? javaEnabled.call(navigator) : null,
45
- language: language || null,
46
- screenHeight: screenHeight || null,
47
- screenWidth: screenWidth || null,
48
- timeZoneOffset: (new Date()).getTimezoneOffset(),
49
- },
50
- },
51
- };
52
-
53
- return data;
54
- }
55
-
56
- async function collectData({
57
- env = null,
58
- kountAccountId = null,
59
- kountSessionId = null,
60
- } = {}) {
61
- return collectDataHelper({
62
- env,
63
- screen,
64
- navigator,
65
- kountAccountId,
66
- kountSessionId,
67
- getFingerprint: fingerprinter,
68
- getFraudSessionId: kount,
69
- });
70
- }
71
-
72
- export { collectData, collectDataHelper };
@@ -1,37 +0,0 @@
1
- import Fingerprint2 from '@fingerprintjs/fingerprintjs';
2
-
3
- /**
4
- * generateFingerprint is implemented following guidelines
5
- * from the @fingerprintjs/fingerprintjs package documentation:
6
- * https://github.com/fingerprintjs/fingerprintjs#get-and-getpromise
7
- */
8
- async function generateFingerprint() {
9
- try {
10
- const components = await Fingerprint2.getPromise();
11
- const values = components.map((comp) => comp.value);
12
- const murmur = Fingerprint2.x64hash128(values.join(''), 31);
13
-
14
- return murmur;
15
- } catch (e) {
16
- // eslint-disable-next-line no-console
17
- console.log(e);
18
-
19
- return '';
20
- }
21
- }
22
-
23
- export default async function getFingerprint() {
24
- return new Promise((resolve) => {
25
- if (window.requestIdleCallback) {
26
- requestIdleCallback(async () => {
27
- const fingerprint = await generateFingerprint();
28
- resolve(fingerprint);
29
- });
30
- } else {
31
- setTimeout(async () => {
32
- const fingerprint = await generateFingerprint();
33
- resolve(fingerprint);
34
- }, 500);
35
- }
36
- });
37
- }
package/src/kount.js DELETED
@@ -1,52 +0,0 @@
1
- /* eslint-disable no-undef */
2
- const sandboxDataCollectorUrl = 'https://tst.kaptcha.com';
3
- const prodDataCollectorUrl = 'https://ssl.kaptcha.com';
4
-
5
- const isProd = (env) => env === 'production';
6
-
7
- const addKountScriptElement = ({
8
- env,
9
- kountAccountId,
10
- kountSessionId,
11
- }) => {
12
- const baseUrl = isProd(env) ? prodDataCollectorUrl : sandboxDataCollectorUrl;
13
- const kountScriptUrl = new URL(`${baseUrl}/collect/sdk`);
14
- kountScriptUrl.searchParams.append('m', kountAccountId);
15
- if (kountSessionId) {
16
- kountScriptUrl.searchParams.append('m', kountSessionId);
17
- }
18
-
19
- const kountScript = document.createElement('script');
20
- kountScript.setAttribute('class', 'kaxsdc');
21
- kountScript.setAttribute('data-event', 'load');
22
- kountScript.setAttribute('type', 'text/javascript');
23
- kountScript.setAttribute('src', kountScriptUrl.href);
24
-
25
- document.body.append(kountScript);
26
-
27
- return kountScript;
28
- };
29
-
30
- export default async function getFraudSessionId({ env, kountAccountId, kountSessionId }) {
31
- return new Promise((resolve, reject) => {
32
- const kountScript = addKountScriptElement({
33
- env,
34
- kountAccountId,
35
- kountSessionId,
36
- });
37
-
38
- kountScript.onload = () => {
39
- const client = new ka.ClientSDK();
40
- client.setupCallback({
41
- 'collect-begin': (params) => {
42
- const { MercSessId } = params;
43
- resolve(MercSessId);
44
- },
45
- });
46
- client.autoLoadEvents();
47
- };
48
- kountScript.onerror = () => {
49
- reject(new Error('Error attempting to mount Kount script'));
50
- };
51
- });
52
- }