Skip to content

Commit

Permalink
Merge pull request #1161 from OneSignal/fix/CreateUserHeader
Browse files Browse the repository at this point in the history
[Fix] Add OneSignal-Subscription-Id header to create user requests
  • Loading branch information
shepherd-l authored Mar 6, 2024
2 parents e35a9b4 + 0cbdc2d commit d3d7736
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 17 deletions.
28 changes: 27 additions & 1 deletion __test__/unit/http/sdkVersion.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import Environment from '../../../src/shared/helpers/Environment';
import { RequestService } from '../../../src/core/requestService/RequestService';
import { APP_ID, DUMMY_EXTERNAL_ID } from '../../support/constants';
import {
APP_ID,
DUMMY_EXTERNAL_ID,
DUMMY_SUBSCRIPTION_ID,
} from '../../support/constants';
import { expectHeaderToBeSent } from '../../support/helpers/sdkVersion';
import AliasPair from '../../../src/core/requestService/AliasPair';
import { getDummyPushSubscriptionOSModel } from '../../support/helpers/core';
Expand Down Expand Up @@ -46,6 +50,20 @@ describe('Sdk Version Header Tests', () => {
RequestService.createUser({ appId: APP_ID }, {});
expectHeaderToBeSent();
});
test('POST /users: header is sent', () => {
RequestService.createUser(
{ appId: APP_ID },
{ refresh_device_metadata: true },
);
expectHeaderToBeSent();
});
test('POST /users: header is sent with subscription id', () => {
RequestService.createUser(
{ appId: APP_ID, subscriptionId: DUMMY_SUBSCRIPTION_ID },
{},
);
expectHeaderToBeSent();
});
test('GET /users/by/<alias_label>/<alias_id>: header is sent', () => {
RequestService.getUser(
{ appId: APP_ID },
Expand All @@ -61,6 +79,14 @@ describe('Sdk Version Header Tests', () => {
);
expectHeaderToBeSent();
});
test('PATCH /users/by/<alias_label>/<alias_id>: header is sent with subscription id', () => {
RequestService.updateUser(
{ appId: APP_ID, subscriptionId: DUMMY_SUBSCRIPTION_ID },
new AliasPair(AliasPair.EXTERNAL_ID, DUMMY_EXTERNAL_ID),
{},
);
expectHeaderToBeSent();
});
test('DELETE /users/by/<alias_label>/<alias_id>: header is sent', () => {
RequestService.deleteUser(
{ appId: APP_ID },
Expand Down
10 changes: 10 additions & 0 deletions src/core/requestService/CreateUserPayload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SupportedIdentity } from '../models/IdentityModel';
import { SupportedSubscription } from '../models/SubscriptionModels';
import { UserPropertiesModel } from '../models/UserPropertiesModel';

export type CreateUserPayload = {
properties?: UserPropertiesModel;
identity?: SupportedIdentity;
refresh_device_metadata?: boolean;
subscriptions?: SupportedSubscription[];
};
29 changes: 21 additions & 8 deletions src/core/requestService/RequestService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from '../models/SubscriptionModels';
import AliasPair from './AliasPair';
import { UpdateUserPayload } from './UpdateUserPayload';
import UserData from '../models/UserData';
import { CreateUserPayload } from './CreateUserPayload';
import { RequestMetadata } from '../models/RequestMetadata';
import { encodeRFC3986URIComponent } from '../../shared/utils/Encoding';
import OneSignalUtils from '../../shared/utils/OneSignalUtils';
Expand All @@ -26,14 +26,27 @@ export class RequestService {
*/
static async createUser(
requestMetadata: RequestMetadata,
requestBody: Partial<UserData>,
requestBody: CreateUserPayload,
): Promise<OneSignalApiBaseResponse> {
const { appId } = requestMetadata;
return OneSignalApiBase.post(
`apps/${appId}/users`,
requestBody,
requestMetadata.jwtHeader,
);
const { appId, subscriptionId } = requestMetadata;

const subscriptionHeader = subscriptionId
? { 'OneSignal-Subscription-Id': subscriptionId }
: undefined;

let headers = {};

if (subscriptionHeader) {
headers = { ...headers, ...subscriptionHeader };
}

if (requestMetadata.jwtHeader) {
headers = { ...headers, ...requestMetadata.jwtHeader };
}

requestBody['refresh_device_metadata'] = true;

return OneSignalApiBase.post(`apps/${appId}/users`, requestBody, headers);
}

/**
Expand Down
19 changes: 16 additions & 3 deletions src/core/requestService/UserPropertyRequests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { RequestService } from './RequestService';
import MainHelper from '../../shared/helpers/MainHelper';
import OneSignalApiBaseResponse from '../../shared/api/OneSignalApiBaseResponse';
import Log from '../../shared/libraries/Log';
import { isCompleteSubscriptionObject } from '../utils/typePredicates';

/**
* This class contains logic for all the UserProperty model related requests that can be made to the OneSignal API
Expand Down Expand Up @@ -44,9 +45,21 @@ export default class UserPropertyRequests {
);

const appId = await MainHelper.getAppId();
const response = await RequestService.updateUser({ appId }, aliasPair, {
properties,
});
const pushSubscription =
await OneSignal.coreDirector.getPushSubscriptionModel();

let subscriptionId;
if (isCompleteSubscriptionObject(pushSubscription?.data)) {
subscriptionId = pushSubscription?.data.id;
}

const response = await RequestService.updateUser(
{ appId, subscriptionId },
aliasPair,
{
properties,
},
);
return UserPropertyRequests._processUserPropertyResponse(response);
}

Expand Down
14 changes: 13 additions & 1 deletion src/onesignal/UserDirector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { logMethodCall } from '../shared/utils/utils';
import User from './User';
import { RequestService } from '../core/requestService/RequestService';
import { SupportedSubscription } from '../core/models/SubscriptionModels';
import { isCompleteSubscriptionObject } from '../core/utils/typePredicates';

export default class UserDirector {
static async initializeUser(isTemporary?: boolean): Promise<void> {
Expand Down Expand Up @@ -95,8 +96,19 @@ export default class UserDirector {

try {
const appId = await MainHelper.getAppId();
const pushSubscription =
await OneSignal.coreDirector.getPushSubscriptionModel();

let subscriptionId;
if (isCompleteSubscriptionObject(pushSubscription?.data)) {
subscriptionId = pushSubscription?.data.id;
}

const userData = await UserDirector.getAllUserData();
const response = await RequestService.createUser({ appId }, userData);
const response = await RequestService.createUser(
{ appId, subscriptionId },
userData,
);
user.isCreatingUser = false;
return response.result as UserData;
} catch (e) {
Expand Down
12 changes: 8 additions & 4 deletions src/page/managers/LoginManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export default class LoginManager {

if (isIdentified) {
// if started off identified, upsert a user
result = await this.upsertUser(userData);
result = await this.upsertUser(userData, subscriptionId);
} else {
// promoting anonymous user to identified user
// from user data, we only use identity (and we remove all aliases except external_id)
Expand All @@ -196,9 +196,10 @@ export default class LoginManager {

static async upsertUser(
userData: Partial<UserData>,
subscriptionId?: string,
retry = 5,
): Promise<UserData> {
logMethodCall('LoginManager.upsertUser', { userData });
logMethodCall('LoginManager.upsertUser', { userData, subscriptionId });

if (retry === 0) {
throw new OneSignalError('Login: upsertUser failed: max retries reached');
Expand All @@ -210,7 +211,10 @@ export default class LoginManager {
// only accepts one alias, so remove other aliases only leaving external_id
this.stripAliasesOtherThanExternalId(userData);

const response = await RequestService.createUser({ appId }, userData);
const response = await RequestService.createUser(
{ appId, subscriptionId },
userData,
);
const result = response?.result;
const status = response?.status;

Expand All @@ -221,7 +225,7 @@ export default class LoginManager {
} else if (status >= 500) {
Log.error('Server error. Retrying...');
await awaitableTimeout(RETRY_BACKOFF[retry]);
return this.upsertUser(userDataCopy, retry - 1);
return this.upsertUser(userDataCopy, subscriptionId, retry - 1);
}

return result;
Expand Down

0 comments on commit d3d7736

Please sign in to comment.