Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MOB-9522]: Fix JWT UserID Support #452

Merged
merged 18 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2343,20 +2343,17 @@ At that point, further requests to Iterable's API will fail.

To perform a manual JWT token refresh, call [`refreshJwtToken`](#refreshjwttoken).

# Iterable's European data center (EUDC)
# Iterable's European data center (EDC)

If your Iterable project is hosted on Iterable's [European data center (EUDC)](https://support.iterable.com/hc/articles/17572750887444),
If your Iterable project is hosted on Iterable's [European data center (EDC)](https://support.iterable.com/hc/articles/17572750887444),
you'll need to configure Iterable's Web SDK to interact with Iterable's EU-based
API endpoints.

To do this, you have two options:
To do this:

- On the web server that hosts your site, set the `IS_EU_ITERABLE_SERVICE`
environment variable to `true`.

- Or, when use [`initializeWithConfig`](#initializeWithConfig) to initialize
the SDK (rather then [`initialize`](#initialize)), and set set the
`isEuIterableService` configuration option to `true`. For example:
- Use [`initializeWithConfig`](#initializeWithConfig) to initialize the SDK
(rather then [`initialize`](#initialize)).
- Set the `isEuIterableService` configuration option to `true`. For example:

```ts
import { initializeWithConfig } from '@iterable/web-sdk';
Expand Down
34 changes: 24 additions & 10 deletions example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1470,12 +1470,19 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"

braces@^3.0.2, braces@~3.0.2:
braces@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
dependencies:
fill-range "^7.1.1"

braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
fill-range "^7.0.1"
fill-range "^7.1.1"

browser-process-hrtime@^1.0.0:
version "1.0.0"
Expand Down Expand Up @@ -2379,10 +2386,17 @@ file-entry-cache@^6.0.1:
dependencies:
flat-cache "^3.0.4"

fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
fill-range@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
dependencies:
to-regex-range "^5.0.1"

fill-range@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
dependencies:
to-regex-range "^5.0.1"

Expand Down Expand Up @@ -3592,11 +3606,11 @@ methods@~1.1.2:
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==

micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
version "4.0.8"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
dependencies:
braces "^3.0.2"
braces "^3.0.3"
picomatch "^2.3.1"

mime-db@1.51.0:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@iterable/web-sdk",
"description": "Iterable SDK for JavaScript and Node.",
"version": "1.1.1",
"version": "1.1.2",
"homepage": "https://iterable.com/",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion react-example/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const HomeLink = styled(Link)`
{
exp_minutes: 2,
email,
userId: userID,
user_id: userID,
jwt_secret: process.env.JWT_SECRET
},
{
Expand Down
2 changes: 1 addition & 1 deletion react-example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@
integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==

"@iterable/web-sdk@../":
version "1.1.1"
version "1.1.2"
dependencies:
"@pabra/sortby" "^1.0.1"
"@types/ws" "8.5.4"
Expand Down
33 changes: 10 additions & 23 deletions src/authorization/authorization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ describe('API Key Interceptors', () => {
packageName: 'my-lil-website'
});
expect(response.config.headers['Api-Key']).toBe('123');
expect(response.config.headers['Authorization']).toBe(
expect(response.config.headers.Authorization).toBe(
`Bearer ${MOCK_JWT_KEY}`
);
});
Expand All @@ -125,7 +125,7 @@ describe('API Key Interceptors', () => {
packageName: 'my-lil-website'
});
expect(response.config.headers['Api-Key']).toBe('123');
expect(response.config.headers['Authorization']).toBe(
expect(response.config.headers.Authorization).toBe(
`Bearer ${MOCK_JWT_KEY}`
);
});
Expand Down Expand Up @@ -230,8 +230,8 @@ describe('API Key Interceptors', () => {
await updateUserEmail('helloworld@gmail.com');

jest.advanceTimersByTime(60000 * 4.1);
/*
called once originally, a second time after the email was changed,
/*
called once originally, a second time after the email was changed,
and a third after the JWT was about to expire
*/
expect(mockGenerateJWT).toHaveBeenCalledTimes(3);
Expand Down Expand Up @@ -279,8 +279,8 @@ describe('API Key Interceptors', () => {
});

jest.advanceTimersByTime(60000 * 4.1);
/*
called once originally, a second time after the email was changed,
/*
called once originally, a second time after the email was changed,
and a third after the JWT was about to expire
*/
expect(mockGenerateJWT).toHaveBeenCalledTimes(3);
Expand Down Expand Up @@ -313,8 +313,8 @@ describe('API Key Interceptors', () => {
});

jest.advanceTimersByTime(60000 * 4.1);
/*
called once originally, a second time after the email was changed,
/*
called once originally, a second time after the email was changed,
and a third after the JWT was about to expire
*/
expect(mockGenerateJWT).toHaveBeenCalledTimes(3);
Expand Down Expand Up @@ -671,19 +671,6 @@ describe('User Identification', () => {
expect(response.config.params.email).toBeUndefined();
expect(response.config.params.userId).toBe('999');
});

it('should try /users/update 0 times if request to create a user fails', async () => {
mockRequest.onPost('/users/update').reply(400, {});

const { setUserID } = initialize('123');
await setUserID('999');

expect(
mockRequest.history.post.filter(
(e: any) => !!e.url?.match(/users\/update/gim)
).length
).toBe(1);
});
});
});

Expand Down Expand Up @@ -1075,7 +1062,7 @@ describe('User Identification', () => {
packageName: 'my-lil-website'
});
expect(response.config.headers['Api-Key']).toBe('123');
expect(response.config.headers['Authorization']).toBe(
expect(response.config.headers.Authorization).toBe(
`Bearer ${MOCK_JWT_KEY}`
);
});
Expand All @@ -1092,7 +1079,7 @@ describe('User Identification', () => {
packageName: 'my-lil-website'
});
expect(response.config.headers['Api-Key']).toBe('123');
expect(response.config.headers['Authorization']).toBe(
expect(response.config.headers.Authorization).toBe(
`Bearer ${MOCK_JWT_KEY}`
);
});
Expand Down
64 changes: 3 additions & 61 deletions src/authorization/authorization.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/* eslint-disable */
import axios from 'axios';
import { baseAxiosRequest, baseIterableRequest } from '../request';
import { baseAxiosRequest } from '../request';
import { clearMessages } from 'src/inapp/inapp';
import {
IS_PRODUCTION,
RETRY_USER_ATTEMPTS,
STATIC_HEADERS,
SHARED_PREF_ANON_USER_ID,
ENDPOINTS,
Expand All @@ -25,8 +24,6 @@ import {
registerAnonUserIdSetter
} from 'src/anonymousUserTracking/anonymousUserEventManager';
import { Options, config } from 'src/utils/config';
import { IterableResponse } from 'src/types';
import { updateUserSchema } from 'src/users/users.schema';

const MAX_TIMEOUT = ONE_DAY;
/*
Expand Down Expand Up @@ -82,7 +79,7 @@ export interface WithoutJWT {
export const setAnonUserId = async (userId: string) => {
let token: null | string = null;
if (generateJWTGlobal) {
token = await generateJWTGlobal({ userId: userId });
token = await generateJWTGlobal({ userID: userId });
}

baseAxiosRequest.interceptors.request.use((config) => {
Expand All @@ -102,19 +99,6 @@ const clearAnonymousUser = () => {
localStorage.removeItem(SHARED_PREF_ANON_USER_ID);
};

const updateUser = () => {
return baseIterableRequest<IterableResponse>({
method: 'POST',
url: ENDPOINTS.users_update.route,
data: {
preferUserId: true
},
validation: {
data: updateUserSchema
}
});
};

const getAnonUserId = () => {
if (config.getConfig('enableAnonTracking')) {
const anonUser = localStorage.getItem(SHARED_PREF_ANON_USER_ID);
Expand Down Expand Up @@ -517,34 +501,12 @@ export function initialize(
},
setUserID: async (userId: string, merge?: boolean) => {
clearMessages();
const tryUser = () => {
let createUserAttempts = 0;
return async function tryUserNTimes(): Promise<any> {
try {
return await updateUser();
} catch (e) {
if (createUserAttempts < RETRY_USER_ATTEMPTS) {
createUserAttempts += 1;
return tryUserNTimes();
}

return Promise.reject(
`could not create user after ${createUserAttempts} tries`
);
}
};
};
try {
merge = getMergeDefaultValue(merge);
const result = await tryMergeUser(userId, false, merge);
if (result) {
initializeUserIdAndSync(userId, merge);
try {
return await tryUser()();
} catch (e) {
/* failed to create a new user. Just silently resolve */
return Promise.resolve();
}
return Promise.resolve();
}
} catch (error) {
// here we will not sync events but just bubble up error of merge
Expand Down Expand Up @@ -858,25 +820,6 @@ export function initialize(
},
setUserID: async (userId: string, merge?: boolean) => {
clearMessages();

const tryUser = () => {
let createUserAttempts = 0;

return async function tryUserNTimes(): Promise<any> {
try {
return await updateUser();
} catch (e) {
if (createUserAttempts < RETRY_USER_ATTEMPTS) {
createUserAttempts += 1;
return tryUserNTimes();
}

return Promise.reject(
`could not create user after ${createUserAttempts} tries`
);
}
};
};
try {
merge = getMergeDefaultValue(merge);
const result = await tryMergeUser(userId, false, merge);
Expand All @@ -885,7 +828,6 @@ export function initialize(
try {
return doRequest({ userID: userId })
.then(async (token) => {
await tryUser()();
return token;
})
.catch((e) => {
Expand Down
Loading
Loading