diff --git a/src/core/modelRepo/OperationModelStore.ts b/src/core/modelRepo/OperationModelStore.ts index d222c80ac..fe6bc242e 100644 --- a/src/core/modelRepo/OperationModelStore.ts +++ b/src/core/modelRepo/OperationModelStore.ts @@ -3,6 +3,7 @@ import { IPreferencesService } from 'src/types/preferences'; import { OPERATION_NAME } from '../executors/constants'; import { CreateSubscriptionOperation } from '../operations/CreateSubscriptionOperation'; import { DeleteAliasOperation } from '../operations/DeleteAliasOperation'; +import { DeleteSubscriptionOperation } from '../operations/DeleteSubscriptionOperation'; import { DeleteTagOperation } from '../operations/DeleteTagOperation'; import { Operation } from '../operations/Operation'; import { RefreshUserOperation } from '../operations/RefreshUserOperation'; @@ -11,7 +12,10 @@ import { SetPropertyOperation } from '../operations/SetPropertyOperation'; import { SetTagOperation } from '../operations/SetTagOperation'; import { TrackSessionEndOperation } from '../operations/TrackSessionEndOperation'; import { TrackSessionStartOperation } from '../operations/TrackSessionStartOperation'; +import { TransferSubscriptionOperation } from '../operations/TransferSubscriptionOperation'; +import { UpdateSubscriptionOperation } from '../operations/UpdateSubscriptionOperation'; import { ModelStore } from './ModelStore'; + export class OperationModelStore extends ModelStore { constructor(prefs: IPreferencesService) { super('operations', prefs); @@ -45,6 +49,15 @@ export class OperationModelStore extends ModelStore { case OPERATION_NAME.CREATE_SUBSCRIPTION: operation = new CreateSubscriptionOperation(); break; + case OPERATION_NAME.UPDATE_SUBSCRIPTION: + operation = new UpdateSubscriptionOperation(); + break; + case OPERATION_NAME.DELETE_SUBSCRIPTION: + operation = new DeleteSubscriptionOperation(); + break; + case OPERATION_NAME.TRANSFER_SUBSCRIPTION: + operation = new TransferSubscriptionOperation(); + break; case OPERATION_NAME.REFRESH_USER: operation = new RefreshUserOperation(); break; diff --git a/src/core/operations/BaseSubscriptionOperation.ts b/src/core/operations/BaseSubscriptionOperation.ts new file mode 100644 index 000000000..6f2b5d535 --- /dev/null +++ b/src/core/operations/BaseSubscriptionOperation.ts @@ -0,0 +1,148 @@ +import { IDManager } from 'src/shared/managers/IDManager'; +import { SubscriptionStateKind } from 'src/shared/models/SubscriptionStateKind'; +import { SubscriptionType } from '../models/SubscriptionModels'; +import { Operation } from './Operation'; +import { Subscription } from './types'; + +/** + * Base class for subscription-related operations + */ +export abstract class BaseSubscriptionOperation extends Operation { + constructor( + operationName: string, + appId?: string, + onesignalId?: string, + subscription?: Subscription, + ) { + super(operationName, appId, onesignalId); + + if (subscription) { + this.subscriptionId = subscription.subscriptionId; + this.type = subscription.type; + this.enabled = subscription.enabled; + this.notification_types = subscription.notification_types; + this.sdk = subscription.sdk; + this.device_model = subscription.device_model; + this.device_os = subscription.device_os; + this.web_auth = subscription.web_auth; + this.web_p256 = subscription.web_p256; + } + } + + /** + * The subscription ID for the operation. This ID *may* be locally generated + * and can be checked via IDManager.isLocalId to ensure correct processing. + */ + get subscriptionId(): string { + return this.getProperty('subscriptionId'); + } + protected set subscriptionId(value: string) { + this.setProperty('subscriptionId', value); + } + + /** + * The type of subscription. + */ + get type(): SubscriptionType { + return this.getProperty('type'); + } + protected set type(value: SubscriptionType) { + this.setProperty('type', value); + } + + /** + * Whether this subscription is currently enabled. + */ + get enabled(): boolean { + return this.getProperty('enabled'); + } + protected set enabled(value: boolean) { + this.setProperty('enabled', value); + } + + /** + * The notification types this subscription is subscribed to. + */ + get notification_types(): SubscriptionStateKind { + return this.getProperty('notification_types'); + } + protected set notification_types(value: SubscriptionStateKind) { + this.setProperty('notification_types', value); + } + + /** + * The SDK identifier + */ + get sdk(): string | undefined { + return this.getProperty('sdk'); + } + protected set sdk(value: string | undefined) { + this.setProperty('sdk', value); + } + + /** + * The device model + */ + get device_model(): string | undefined { + return this.getProperty('device_model'); + } + protected set device_model(value: string | undefined) { + this.setProperty('device_model', value); + } + + /** + * The device OS version + */ + get device_os(): number | undefined { + return this.getProperty('device_os'); + } + protected set device_os(value: number | undefined) { + this.setProperty('device_os', value); + } + + /** + * Web authentication value + */ + get web_auth(): string | undefined { + return this.getProperty('web_auth'); + } + protected set web_auth(value: string | undefined) { + this.setProperty('web_auth', value); + } + + /** + * Web P256 value + */ + get web_p256(): string | undefined { + return this.getProperty('web_p256'); + } + protected set web_p256(value: string | undefined) { + this.setProperty('web_p256', value); + } + + override get createComparisonKey(): string { + return `${this.appId}.User.${this.onesignalId}`; + } + + override get modifyComparisonKey(): string { + return `${this.appId}.User.${this.onesignalId}.Subscription.${this.subscriptionId}`; + } + + override get canStartExecute(): boolean { + return ( + !IDManager.isLocalId(this.onesignalId) && + !IDManager.isLocalId(this.subscriptionId) + ); + } + + override get applyToRecordId(): string { + return this.subscriptionId; + } + + override translateIds(map: Record): void { + super.translateIds(map); + if (map[this.subscriptionId]) { + this.subscriptionId = map[this.subscriptionId]; + } + } +} diff --git a/src/core/operations/CreateSubscriptionOperation.ts b/src/core/operations/CreateSubscriptionOperation.ts index 6482e4ae1..2219ec2b0 100644 --- a/src/core/operations/CreateSubscriptionOperation.ts +++ b/src/core/operations/CreateSubscriptionOperation.ts @@ -1,114 +1,33 @@ -import { SubscriptionStateKind } from 'src/shared/models/SubscriptionStateKind'; +import { IDManager } from 'src/shared/managers/IDManager'; import { OPERATION_NAME } from '../executors/constants'; -import { SubscriptionType } from '../models/SubscriptionModels'; -import { Operation } from './Operation'; +import { BaseSubscriptionOperation } from './BaseSubscriptionOperation'; import { Subscription } from './types'; /** * An Operation to create a new subscription in the OneSignal backend. The subscription will * be associated to the user with the appId and onesignalId provided. */ -export class CreateSubscriptionOperation extends Operation { +export class CreateSubscriptionOperation extends BaseSubscriptionOperation { constructor(subscription?: Subscription) { super( OPERATION_NAME.CREATE_SUBSCRIPTION, subscription?.appId, subscription?.onesignalId, + subscription, ); - if (subscription) { - this.subscriptionId = subscription.subscriptionId; - this.type = subscription.type; - this.enabled = subscription.enabled; - this.notification_types = subscription.notification_types; - this.sdk = subscription.sdk; - this.device_model = subscription.device_model; - this.device_os = subscription.device_os; - this.web_auth = subscription.web_auth; - this.web_p256 = subscription.web_p256; - } - } - - /** - * The local ID of the subscription being created. The subscription model with this ID will have its - * ID updated with the backend-generated ID post-create. - */ - get subscriptionId(): string { - return this.getProperty('subscriptionId'); - } - private set subscriptionId(value: string) { - this.setProperty('subscriptionId', value); - } - - /** - * The type of subscription. - */ - get type(): SubscriptionType { - return this.getProperty('type'); - } - private set type(value: SubscriptionType) { - this.setProperty('type', value); } - /** - * Whether this subscription is currently enabled. - */ - get enabled(): boolean { - return this.getProperty('enabled'); - } - private set enabled(value: boolean) { - this.setProperty('enabled', value); + override get canStartExecute(): boolean { + return !IDManager.isLocalId(this.onesignalId); } - /** - * The notification types this subscription is subscribed to. - */ - get notification_types(): SubscriptionStateKind { - return this.getProperty('notification_types'); - } - private set notification_types(value: SubscriptionStateKind) { - this.setProperty('notification_types', value); + override get applyToRecordId(): string { + return this.onesignalId; } - get sdk(): string | undefined { - return this.getProperty('sdk'); - } - private set sdk(value: string | undefined) { - this.setProperty('sdk', value); - } - - get device_model(): string | undefined { - return this.getProperty('device_model'); - } - private set device_model(value: string | undefined) { - this.setProperty('device_model', value); - } - - get device_os(): number | undefined { - return this.getProperty('device_os'); - } - private set device_os(value: number | undefined) { - this.setProperty('device_os', value); - } - - get web_auth(): string | undefined { - return this.getProperty('web_auth'); - } - private set web_auth(value: string | undefined) { - this.setProperty('web_auth', value); - } - - get web_p256(): string | undefined { - return this.getProperty('web_p256'); - } - private set web_p256(value: string | undefined) { - this.setProperty('web_p256', value); - } - - override get createComparisonKey(): string { - return `${this.appId}.User.${this.onesignalId}`; - } - - override get modifyComparisonKey(): string { - return `${this.appId}.User.${this.onesignalId}.Subscription.${this.subscriptionId}`; + override translateIds(map: Record): void { + if (map[this.onesignalId]) { + this.onesignalId = map[this.onesignalId]; + } } } diff --git a/src/core/operations/DeleteSubscriptionOperation.ts b/src/core/operations/DeleteSubscriptionOperation.ts new file mode 100644 index 000000000..0ffc16898 --- /dev/null +++ b/src/core/operations/DeleteSubscriptionOperation.ts @@ -0,0 +1,19 @@ +import { OPERATION_NAME } from '../executors/constants'; +import { BaseSubscriptionOperation } from './BaseSubscriptionOperation'; +import { GroupComparisonType, GroupComparisonValue } from './Operation'; + +/** + * An Operation to delete a subscription from the OneSignal backend. + */ +export class DeleteSubscriptionOperation extends BaseSubscriptionOperation { + constructor(appId?: string, onesignalId?: string, subscriptionId?: string) { + super(OPERATION_NAME.DELETE_SUBSCRIPTION, appId, onesignalId); + if (subscriptionId) { + this.subscriptionId = subscriptionId; + } + } + + override get groupComparisonType(): GroupComparisonValue { + return GroupComparisonType.NONE; + } +} diff --git a/src/core/operations/TransferSubscriptionOperation.ts b/src/core/operations/TransferSubscriptionOperation.ts new file mode 100644 index 000000000..318e92876 --- /dev/null +++ b/src/core/operations/TransferSubscriptionOperation.ts @@ -0,0 +1,23 @@ +import { OPERATION_NAME } from '../executors/constants'; +import { BaseSubscriptionOperation } from './BaseSubscriptionOperation'; +import { GroupComparisonType, GroupComparisonValue } from './Operation'; + +/** + * An Operation to transfer a subscription to a new owner on the OneSignal backend. + */ +export class TransferSubscriptionOperation extends BaseSubscriptionOperation { + constructor(appId?: string, onesignalId?: string, subscriptionId?: string) { + super(OPERATION_NAME.TRANSFER_SUBSCRIPTION, appId, onesignalId); + if (subscriptionId) { + this.subscriptionId = subscriptionId; + } + } + + override get groupComparisonType(): GroupComparisonValue { + return GroupComparisonType.NONE; + } + + override get modifyComparisonKey(): string { + return `${this.appId}.Subscription.${this.subscriptionId}.Transfer`; + } +} diff --git a/src/core/operations/UpdateSubscriptionOperation.ts b/src/core/operations/UpdateSubscriptionOperation.ts new file mode 100644 index 000000000..173bfb777 --- /dev/null +++ b/src/core/operations/UpdateSubscriptionOperation.ts @@ -0,0 +1,17 @@ +import { OPERATION_NAME } from '../executors/constants'; +import { BaseSubscriptionOperation } from './BaseSubscriptionOperation'; +import { Subscription } from './types'; + +/** + * An Operation to update an existing subscription in the OneSignal backend. + */ +export class UpdateSubscriptionOperation extends BaseSubscriptionOperation { + constructor(subscription?: Subscription) { + super( + OPERATION_NAME.UPDATE_SUBSCRIPTION, + subscription?.appId, + subscription?.onesignalId, + subscription, + ); + } +}