Merge pull request #23457 from overleaf/ar-recurly-account-mapping-initial

[web] setup Recurly -> Mongo account mapping

GitOrigin-RevId: ee08cad60ee04e62100f3d5a4f76fdbcf5543917
This commit is contained in:
Andrew Rumble
2025-02-21 09:04:45 +00:00
committed by Copybot
parent be247b8cc9
commit 0e64fe2b21
10 changed files with 559 additions and 308 deletions
@@ -0,0 +1,97 @@
const mappings = new Map([
['salesforce_id', generateSubscriptionToSalesforceMapping],
['v1_id', generateSubscriptionToV1Mapping],
['recurlySubscription_id', generateSubscriptionToRecurlyMapping],
])
/**
* @typedef {(import('./types.d.ts').AccountMapping)} AccountMapping
*/
/**
*
* @param {Object} subscription
* @param {Object} updatedSubscription
* @return {Array<AccountMapping>}
*/
function extractAccountMappingsFromSubscription(
subscription,
updatedSubscription
) {
const accountMappings = []
mappings.forEach((generateMapping, param) => {
if (updatedSubscription[param] || updatedSubscription[param] === '') {
if (subscription[param] !== updatedSubscription[param]) {
accountMappings.push(
generateMapping(subscription.id, updatedSubscription[param])
)
}
}
})
return accountMappings
}
function generateV1Mapping(v1Id, salesforceId, createdAt) {
return {
source: 'salesforce',
sourceEntity: 'account',
sourceEntityId: salesforceId,
target: 'v1',
targetEntity: 'university',
targetEntityId: v1Id,
createdAt,
}
}
function generateSubscriptionToV1Mapping(subscriptionId, v1Id) {
return {
source: 'v1',
sourceEntity: 'university',
sourceEntityId: v1Id,
target: 'v2',
targetEntity: 'subscription',
targetEntityId: subscriptionId,
createdAt: new Date().toISOString(),
}
}
function generateSubscriptionToSalesforceMapping(subscriptionId, salesforceId) {
return {
source: 'salesforce',
sourceEntity: 'account',
sourceEntityId: salesforceId,
target: 'v2',
targetEntity: 'subscription',
targetEntityId: subscriptionId,
createdAt: new Date().toISOString(),
}
}
/**
*
* @param {string} subscriptionId
* @param {string} recurlyId
* @param {string} [createdAt] - Should be an ISO date
* @return {AccountMapping}
*/
function generateSubscriptionToRecurlyMapping(
subscriptionId,
recurlyId,
createdAt = new Date().toISOString()
) {
return {
source: 'recurly',
sourceEntity: 'subscription',
sourceEntityId: recurlyId,
target: 'v2',
targetEntity: 'subscription',
targetEntityId: subscriptionId,
createdAt,
}
}
module.exports = {
extractAccountMappingsFromSubscription,
generateV1Mapping,
generateSubscriptionToRecurlyMapping,
}
@@ -1,71 +0,0 @@
export function extractAccountMappingsFromSubscription(
subscription,
updatedSubscription
) {
const accountMappings = []
if (
updatedSubscription.salesforce_id ||
updatedSubscription.salesforce_id === ''
) {
if (subscription.salesforce_id !== updatedSubscription.salesforce_id) {
accountMappings.push(
generateSubscriptionToSalesforceMapping(
subscription.id,
updatedSubscription.salesforce_id
)
)
}
}
if (updatedSubscription.v1_id || updatedSubscription.v1_id === '') {
if (subscription.v1_id !== updatedSubscription.v1_id) {
accountMappings.push(
generateSubscriptionToV1Mapping(
subscription.id,
updatedSubscription.v1_id
)
)
}
}
return accountMappings
}
export function generateV1Mapping(v1Id, salesforceId, createdAt) {
return {
source: 'salesforce',
sourceEntity: 'account',
sourceEntityId: salesforceId,
target: 'v1',
targetEntity: 'university',
targetEntityId: v1Id,
createdAt,
}
}
function generateSubscriptionToV1Mapping(subscriptionId, v1Id) {
return {
source: 'v1',
sourceEntity: 'university',
sourceEntityId: v1Id,
target: 'v2',
targetEntity: 'subscription',
targetEntityId: subscriptionId,
createdAt: new Date().toISOString(),
}
}
function generateSubscriptionToSalesforceMapping(subscriptionId, salesforceId) {
return {
source: 'salesforce',
sourceEntity: 'account',
sourceEntityId: salesforceId,
target: 'v2',
targetEntity: 'subscription',
targetEntityId: subscriptionId,
createdAt: new Date().toISOString(),
}
}
export default {
extractAccountMappingsFromSubscription,
generateV1Mapping,
}
@@ -4,7 +4,7 @@ import SessionManager from '../Authentication/SessionManager.js'
import GeoIpLookup from '../../infrastructure/GeoIpLookup.js'
import Features from '../../infrastructure/Features.js'
import { expressify } from '@overleaf/promise-utils'
import { generateV1Mapping } from './AccountMappingHelper.mjs'
import AccountMappingHelper from './AccountMappingHelper.js'
async function registerSalesforceMapping(req, res, next) {
if (!Features.hasFeature('analytics')) {
@@ -12,7 +12,7 @@ async function registerSalesforceMapping(req, res, next) {
}
const { createdAt, salesforceId, v1Id } = req.body
AnalyticsManager.registerAccountMapping(
generateV1Mapping(v1Id, salesforceId, createdAt)
AccountMappingHelper.generateV1Mapping(v1Id, salesforceId, createdAt)
)
res.sendStatus(202)
}
@@ -146,16 +146,14 @@ function setUserPropertyForSessionInBackground(session, property, value) {
})
}
/**
* @typedef {(import('./types').AccountMapping)} AccountMapping
*/
/**
* Register mapping between two accounts.
*
* @param {object} payload - The event payload to send to Analytics
* @param {string} payload.source - The type of account linked from
* @param {string} payload.sourceId - The ID of the account linked from
* @param {string} payload.target - The type of account linked to
* @param {string} payload.targetId - The ID of the account linked to
* @param {Date} payload.createdAt - The date the mapping was created
* @property
* @param {AccountMapping} payload - The event payload to send to Analytics
*/
function registerAccountMapping({
source,
+9
View File
@@ -0,0 +1,9 @@
export type AccountMapping = {
source: string
sourceEntity: string
sourceEntityId: string
target: string
targetEntity: string
targetEntityId: string
createdAt: string
}
@@ -10,6 +10,7 @@ const { DeletedSubscription } = require('../../models/DeletedSubscription')
const logger = require('@overleaf/logger')
const Features = require('../../infrastructure/Features')
const UserAuditLogHandler = require('../User/UserAuditLogHandler')
const AccountMappingHelper = require('../Analytics/AccountMappingHelper')
const { SSOConfig } = require('../../models/SSOConfig')
/**
@@ -345,6 +346,16 @@ async function updateSubscriptionFromRecurly(
}
}
await subscription.save()
const accountMapping =
AccountMappingHelper.generateSubscriptionToRecurlyMapping(
subscription._id,
subscription.recurlySubscription_id
)
if (accountMapping) {
AnalyticsManager.registerAccountMapping(accountMapping)
}
await _scheduleRefreshFeatures(subscription)
}