# v1.16.12 ## Feature list * [RAKE-792] * [RAKE-722] * [RAKE-668] * [RAKE-598] * [RAKE-793] * [RAKE-634] * [RAKE-751] ## Facebook 24h notification | ENV | Status | | --- | ------ | | TEST| | | UAT | Done | | PROD| Done | Re-subscribe all facebook pages with new event ```messaging_optins``` Run script ```rake-scripts/mongo-db-scripts/1.16.12/facebook-workspaces.js``` ## Bug fixes list ## Services to deploy * admin service | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | * core service | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | * rake user app module | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | * facebook worker | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| inprogress | * event trigger | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| | * api service | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | * user app worker | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | * main worker > disable Facebook platoform before deploy > Facebook worker [TS] | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ## Google cloud | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | dispatch.yaml ``` dispatch: - url: "api.rake.ai/login" service: rake-permissions-prod - url: "docs.rake.ai/*" service: docs-prod - url: "rakesystem.rake.ai/webhook/facebook-messenger/*" service: facebook-worker-prod - url: "rakesystem.rake.ai/facebook-messenger/*" service: facebook-worker-prod - url: "rakesystem.rake.ai/webhook/facebook-messenger/*" service: facebook-worker-prod - url: "rakesystem.rake.ai/facebook-messenger/bots/*" service: facebook-worker-prod - url: "rakesystem.rake.ai/rake-user-app/*" service: user-app-worker-prod - url: "rakesystem.rake.ai/*" service: worker-prod - url: "core.rake.ai/*" service: core-prod - url: "widget.rake.ai/*" service: rake-chat-widget-prod - url: "admin.rake.ai/*" service: admin-prod - url: "*.rake.ai/*" service: rake-user-app-prod ``` ## DB ### Platforms | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | > Facebook worker [TS] ``` db.platforms.update( { platformId: 3 }, { $set: { systemApplicationId: 25 } } ) ``` ### System Application | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | > Facebook worker [TS] ``` db.getCollection("systemApplications").insert({ "systemApplicationId": 25, "name": "facebook-worker", "baseUrl": "https://facebook-worker-prod-dot-rake-system.uc.r.appspot.com", "systemReference": "facebookWorker" }) ``` ### System functions | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | > Facebook worker [TS] ``` db.systemFunctions.updateMany( { systemFunctionId: { $in: [ 71, 614, 557, 120, 119 ] }, }, { $set: { systemApplicationId: 25 } }, ) ``` | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ``` // new API route for documentation service db.systemFunctions.insert({ "systemApplicationId" : 0, "systemFunctionId" : 623, "function" : "/system-applications", "description" : "Get the list of all system applicationsl", "permissionLevel" : "system", "availablePermissionTypeIds" : [ 1 ], "name" : "/system-applications" }); ``` | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ``` // new API route DELETE /sessions/:sessionId/invitations db.systemFunctions.updateOne( { "systemFunctionId" : 609 }, { $addToSet: { availablePermissionTypeIds: { $each: [4,3] } }, $set: { function: '/invitations', name: '/invitations', paths: [ { "id" : "post", "path" : "/sessions/:sessionId/invitations" }, ] }, } ); db.systemFunctions.updateOne( { systemFunctionId: 616 }, { $set: { function: '/invitations/status', name: '/invitations/status', paths: [ { "id" : "patch", "path" : "/sessions/:sessionId/invitations/status" }, ] }, }, ); ``` ### Roles | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ``` // new API route DELETE /sessions/:sessionId/invitations db.roles.updateMany( { 'systemFunctionIds.id': 609 }, { $addToSet: { 'systemFunctionIds.$.availablePermissionTypeIds': 4 } } ) ``` ### Event triggers | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ``` db.eventTriggers.deleteOne({ eventTriggerId: -238 }); db.eventTriggers.insert({ "eventTriggerId" : -238, "description" : "Invite user and create workspace success event.", "eventIds" : [ -174 ], "filters" : [ { "filterOperatorId" : 0, "filterId" : 6, "arguments" : [ { "collectionName" : "{collection.messages.name}", "queryObject" : { "workspaceId" : "{currentWorkspaceId}", "systemEventId" : -174 } }, 1 ] } ], "actions" : [ { "id" : 1, "arguments" : [ { "body" : { "data" : [ { "email" : "{function.getOne('{collection.messages.rawMessages.name}',{ 'rawMessage.workspaceId': {rawMessage.workspaceId},'rawMessage.systemEventId': -137}).getOne('{collection.systemUser.name}',{ systemUserId: result.data.rawMessage.creatorSystemUserId }).setData(result.data.emails.workspaces.find%40e => e.id === {currentWorkspaceId}%41, 'response').getValue('response.email')}", "roleIds" : "{function.getOne('{collection.messages.rawMessages.name}', { 'rawMessage.workspaceId': {rawMessage.workspaceId}, 'rawMessage.systemEventId': -147 }).getValue('rawMessage.data.creatorWorkspaceRoleIds')}" } ] }, "method" : "POST", "url" : "{adminUrl}/{currentWorkspaceId}/system-users", "headers" : { "Authorization" : "0.lo22gendj5i" } } ], "resultField" : "result", "nextActions" : [ { "filters" : [ { "filterOperatorId" : 0, "filterId" : -1, "arguments" : [ "{lastResult.result.statusCode}", 207 ] }, { "filterOperatorId" : 4, "filterId" : -1, "arguments" : [ "{function.setData({lastResult.result.body}).getValue('status')}", 200 ] } ], "actions" : [ { "id" : 1, "arguments" : [ { "body" : { "systemEventId" : -148, "data" : { "workspaceId" : "{rawMessage.workspaceId}", "creatorSystemUserId" : "{function.getOne('{collection.messages.rawMessages.name}', { 'rawMessage.workspaceId': {rawMessage.workspaceId}, 'rawMessage.systemEventId': -137 }).getValue('rawMessage.creatorSystemUserId')}" } }, "method" : "POST", "url" : "{serverUrl}/workspaces/{currentWorkspaceId}/system-events", "headers" : { "Authorization" : "0.lo22gendj5i" } } ] }, { "id" : 1, "arguments" : [ { "body" : { "systemEventId" : -177, "data" : { "workspaceId" : "{rawMessage.workspaceId}", "invitationResponse" : "{function.setData({lastResult.result.body}['0'])}", "systemUser" : "{function.getOne('{collection.messages.rawMessages.name}',{ 'rawMessage.workspaceId': {rawMessage.workspaceId},'rawMessage.systemEventId': -137}).getOne('{collection.systemUser.name}',{ systemUserId: result.data.rawMessage.creatorSystemUserId })}", "templateData" : { "workspace" : "{function.getOne('rawMessages', { 'rawMessage.systemEventId': -137, 'rawMessage.workspaceId': {currentWorkspaceId} }).setData({ data: result.data.rawMessage}, 'response').getValue('response.data')}", "billingPlan" : "{function.getOne('rawMessages', { 'rawMessage.systemEventId': { $in: [-161,-162] }, 'rawMessage.workspaceId': {currentWorkspaceId} }).setData({ plan: result.data.rawMessage.data.plansToAdd['0'].name, billingPlanId: result.data.rawMessage.data.plansToAdd['0'].billingPlanId }, 'response').getValue('response')}", "ownerInfo" : "{function.getOne('{collection.messages.rawMessages.name}',{ 'rawMessage.workspaceId': {rawMessage.workspaceId},'rawMessage.systemEventId': -137}).getOne('{collection.systemUser.name}',{ systemUserId: result.data.rawMessage.creatorSystemUserId }).getOne('{collection.entities.name}', { entityId: result.data.entityId }).setData({ entity: { ...result.data._doc, tokenLink: {lastResult.result.body}['0'].token } }, 'response').getValue('response.entity')}" } } }, "method" : "POST", "url" : "{serverUrl}/workspaces/{currentWorkspaceId}/system-events", "headers" : { "Authorization" : "0.lo22gendj5i" } } ] } ] }, { "filters" : [ { "filterOperatorId" : 1, "filterId" : -1, "arguments" : [ "{lastResult.result.statusCode}", 207 ] }, { "filterOperatorId" : 0, "filterId" : -1, "arguments" : [ "{lastResult.result.statusCode}", 207 ] }, { "filterOperatorId" : 4, "filterId" : -1, "arguments" : [ "{function.setData({lastResult.result.body}).getValue('status')}", 200 ] } ], "customFilter" : "1 OR (2 AND !3)", "actions" : [ { "id" : 1, "arguments" : [ { "body" : { "systemEventId" : -158, "data" : { "statusCode" : "{lastResult.result.statusCode}", "data" : "{lastResult.result.body}", "workspaceId" : "{rawMessage.workspaceId}" } }, "method" : "POST", "url" : "{serverUrl}/workspaces/{currentWorkspaceId}/system-events", "headers" : { "Authorization" : "0.lo22gendj5i" } } ] } ] } ] } ], "customFilter" : "" }) ``` | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ``` db.eventTriggers.deleteOne({ eventTriggerId: -240 }); db.eventTriggers.insert({ "eventTriggerId": -240, "description": "Generate accessToken and send events about workspace created success.", "eventIds": [ -177 ], "filters": [ { "filterOperatorId": 0, "filterId": 6, "arguments": [ { "collectionName": "{collection.messages.name}", "queryObject": { "workspaceId": "{currentWorkspaceId}", "systemEventId": -177 } }, 1 ] } ], "actions": [ { "id": 1, "arguments": [ { "method": "PATCH", "url": "{resourceDefaultsUrl}/resource-defaults/workspaces/platforms", "headers": { "Authorization": "0.lo22gendj5i" }, "body": { "workspaceId": "{rawMessage.workspaceId}", "platforms": "{function.getOne('rawMessages', { 'rawMessage.systemEventId': { $in: [-159] }, 'rawMessage.workspaceId': {currentWorkspaceId} }).setData({ data: result.data.rawMessage.data }, 'response').getValue('response')}" } } ] }, { "id": 1, "arguments": [ { "body": { "to": "{function.getOne('{collection.systemConfig.name}', { 'nodeEnv': 'test' }).getValue('rakeUserApp.workspaceCreationSuccessEmails')}", "templatePath": "admin.workspaceCreationSuccess", "replaceValues": "{rawMessage.templateData}" }, "method": "POST", "url": "{adminUrl}/send-grid", "headers": { "Authorization": "0.lo22gendj5i" } } ] }, { "arguments": [ { "exchange": "stompRakeUserApp", "routingKey": "workspaceId:{currentWorkspaceId}", "headers": { }, "pack": { "event": "workspace-created", "response": { "statusCode": 200, "workspaceId": "{currentWorkspaceId}", "invitationToken": "{rawMessage.invitationResponse.token}", "isRegistered": "{rawMessage.systemUser.isRegistered}", "accessToken": "{rawMessage.invitationResponse.accessToken}", "hasPassword": "{function.exec('{rawMessage.systemUser.password}' != null)}", "systemUser": { "firstName": "{function.getOne('{collection.entities.name}', { 'entityId': {rawMessage.invitationResponse.entityId} }).getValue('firstName')}", "lastName": "{function.getOne('{collection.entities.name}', { 'entityId': {rawMessage.invitationResponse.entityId} }).getValue('lastName')}", "email": "{rawMessage.invitationResponse.user.email}", "systemUserId": "{rawMessage.invitationResponse.systemUserId}", "entityId": "{rawMessage.invitationResponse.entityId}", "profileImageUrl": "{function.getOne('{collection.entities.name}', { 'entityId': {rawMessage.invitationResponse.entityId} }).setData({ fileId: result.data?.profileImage?.fileId }).getOne('{collection.fileEntities.name}', { 'fileId': result.data.fileId } ).getValue('publicUrl')}", "profileColor": "{function.getOne('{collection.entities.name}', { 'entityId': {rawMessage.invitationResponse.entityId} }).getValue('profileImage.color')}" } } } } ], "id": 5 }, { "arguments": [ { "exchange": "services-all", "routingKey": "", "headers": { "instanceId": "{function.getOne('{collection.messages.rawMessages.name}', { 'rawMessage.workspaceId': {currentWorkspaceId}, 'rawMessage.systemEventId': -137 }).getValue('rawMessage.tmpRequestResources.instanceId')}", "systemApplicationId": "{function.getOne('{collection.messages.rawMessages.name}', { 'rawMessage.workspaceId': {currentWorkspaceId}, 'rawMessage.systemEventId': -137 }).getValue('rawMessage.tmpRequestResources.systemApplicationId')}" }, "pack": { "event": "workspace-created", "response": { "statusCode": 200, "workspaceId": "{currentWorkspaceId}", "invitationToken": "{rawMessage.invitationResponse.token}", "isRegistered": "{rawMessage.systemUser.isRegistered}", "accessToken": "{rawMessage.invitationResponse.accessToken}", "hasPassword": "{function.exec('{rawMessage.systemUser.password}' != null)}", "systemUser": { "firstName": "{function.getOne('{collection.entities.name}', { 'entityId': {rawMessage.invitationResponse.entityId} }).getValue('firstName')}", "lastName": "{function.getOne('{collection.entities.name}', { 'entityId': {rawMessage.invitationResponse.entityId} }).getValue('lastName')}", "email": "{rawMessage.invitationResponse.user.email}", "systemUserId": "{rawMessage.invitationResponse.systemUserId}", "entityId": "{rawMessage.invitationResponse.entityId}", "profileImageUrl": "{function.getOne('{collection.entities.name}', { 'entityId': {rawMessage.invitationResponse.entityId} }).setData({ fileId: result.data?.profileImage?.fileId }).getOne('{collection.fileEntities.name}', { 'fileId': result.data.fileId } ).getValue('publicUrl')}", "profileColor": "{function.getOne('{collection.entities.name}', { 'entityId': {rawMessage.invitationResponse.entityId} }).getValue('profileImage.color')}" } } } } ], "id": 5 } ], "customFilter": "" }) ``` ### Tours | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ``` db.userAppTourSteps.deleteOne({ order: 1 }); db.userAppTourSteps.deleteOne({ order: 5 }); db.userAppTourSteps.insert([{ "userAppTourStepId" : 5, "order" : 5, "isGlobalForWorkspace" : true, "roleIds" : [ 8, 9, 11 ], "name" : "Timezone" }, { "userAppTourStepId" : 1, "name" : "Conversations", "roleIds" : [ 7, 8, 9, 10, 11, 12 ], "isGlobalForWorkspace" : false, "order" : 1 }]); // update actions db.userAppTourActions.updateMany({ stepId: 5 }, { $set: { sectionId: 1, stepId: 1 } }) db.userAppTourActions.updateMany({ stepId: 1, actionId: { $in: [42, 39, 38, 37] } }, { $set: { sectionId: 5, stepId: 5 } }) db.userAppTourSteps.update({ userAppTourStepId: 1 }, { $set: { isRequired: true } }) ``` ### System Event -187 | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ``` db.eventTriggers.insert({ "eventTriggerId" : -244, "description" : "Send events about workspace preferences", "eventIds" : [ -187 ], "customFilter" : "", "filters" : [ { "filterOperatorId" : 0, "filterId" : 6, "arguments" : [ { "collectionName" : "{collection.messages.name}", "queryObject" : { "workspaceId" : "{currentWorkspaceId}", "systemEventId" : -187 } }, 1 ] }, { "filterOperatorId" : 0, "filterId" : -1, "arguments" : [ "{rawMessage.stepId}", 2 ] }, { "filterOperatorId" : 0, "filterId" : -1, "arguments" : [ "{rawMessage.isSkipped}", false ] } ], "actions" : [ { "id" : 1, "arguments" : [ { "body" : { "uniqueIndexedEmails" : "{rawMessage.uniqueIndexedEmails}", "firstName" : "{rawMessage.firstName}", "lastName" : "{rawMessage.lastName}", "phoneNumber" : "{rawMessage.phoneNumber}", "systemUserId" : "{rawMessage.systemUserId}", "workspaceId" : "{rawMessage.workspaceId}", "teamSize" : "{rawMessage.teamSize}", "isDeveloper" : "{rawMessage.isDeveloper}", "importantFeatures" : "{rawMessage.importantFeatures}" }, "method" : "PATCH", "url" : "https://us-central1-rake-system-uat.cloudfunctions.net/rake-to-hubspot-internal/system-users", "headers" : { "secret" : "6rAw5HCusu6zYGJF" } } ] } ] }) db.events.insert({ "systemEventId" : -187, "name" : "Send information about workspace preferences", "systemReference" : "workspace.preferences" }) ``` ### Localizations | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ``` db.localizations.insert({ "_id" : ObjectId("61b1e69c2073185c8064aa9c"), "errorCode" : "2_92", "systemReference" : "error.files.tooLarge", "languages" : [ { "code" : "en", "text" : "Cannot save files greater than 2MB" } ], "systemApplicationIds" : [ 2 ] }) ``` ### Tours localizations | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ``` db.localizations.updateOne({ _id: ObjectId('60b8d522bbfe4108fc1c181f') }, { $set: { "languages" : [ { "code" : "en", "text" : "Messages you send and receive will appear here.", "regionCode" : [ ] } ], } }); db.localizations.updateOne({ _id: ObjectId('60b8d4f2bbfe4108fc1c181d') }, { $set: { "languages" : [ { "code" : "en", "text" : "Click your name.", "regionCode" : [ ] } ], } }); db.localizations.updateOne({ _id: ObjectId('60b8d50fbbfe4108fc1c181e') }, { $set: { "languages" : [ { "code" : "en", "text" : "Start typing your message, you can use <ul><li>plain text</li><li>fancy text</li><li>emojis</li><li>GIFs from GIPHY</li><li>attach a file or images</li><li>paste text or images</li><li>create a poll</li><li>send a voice clip</li></ul></br>Press enter to send.", "regionCode" : [ ] } ], } }); ``` ### Mongo Triggers | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| | - workspaces_2_3_workspace - twilio_workspace_2_3 // TODO - rake_live_chat_workspace_2_3 // TODO - whatsAppBusiness_workspace_2_3 // TODO - facebook_workspace_2_3 // TODO - workspaceSystemUsers_2_3 ### Workspace System Users | ENV | Status | | --- | ------ | | TEST| Done | | UAT | Done | | PROD| Done | ``` db.workspaceSystemUsers.updateMany({ entityTypeId: { $exists: false } }, { entityTypeId: 4, }) ``` ### System Events | ENV | Status | | --- | ------ | | TEST| | | UAT | Done | | PROD| Done | ``` const eventActions = [ { "rawMessage" : { "stepId" : 2, "isSkipped" : true, "systemEventId" : -187 }, }, { "rawMessage" : { "stepId" : 1, "isSkipped" : true, "systemEventId" : -187 }, }] const workspaces = db.workspaces.find({}).toArray(); workspaces.forEach((workspace, index) => { console.log(`${index + 1} left from ${workspaces.length} and workspaceId: ${workspace.workspaceId}`); const systemEventExists = db.messages.findOne({ workspaceId: workspace.workspaceId, systemEventId: -187 }); if (systemEventExists) { console.log('systemEventExists for workspace: ', workspace.workspaceId); return; } const payload = eventActions.map((one) => { const { count } = db.identitycounters.findOneAndUpdate({ model: 'rawMessages' }, { $inc: { count: 1 } }, { returnNewDocument: true }); return { ...one, rawMessage: { ...one.rawMessage, workspaceId: workspace.workspaceId, }, rawMessageId: count, } }); db.rawMessages.insertMany(payload); console.log(`done for workspace ${workspace.workspaceId}`); }); ``` UPDATES ``` const event = { "rawMessage" : { "statusCode" : 200, "data" : { "creatorSystemUserId" : 1804, "creatorWorkspaceRoleIds" : [ 9822 ], "creatorSystemUserEmail" : null, "invitationRoleIds" : [ 9823 ], "conditions" : [ ] }, "workspaceId" : 1827, "systemEventId" : -147 }, }; const workspaces = db.workspaces.aggregate([ { $match: { workspaceStatusId: { $nin: [3, 4] } } }, { $lookup: { from: 'rawMessages', let: { workspaceId: '$workspaceId' }, as: 'rawMessages', pipeline: [ { $match: { 'rawMessage.systemEventId': -147, $expr: { $eq: ['$rawMessage.workspaceId', '$$workspaceId'], } } } ] }, }, { $match: { $expr: { $lt: [{ $size: '$rawMessages' }, 1] } } } ]).toArray(); const config = db.systemConfigs.findOne({ nodeEnv: 'uat' }); const { resourceDefaults: { roles } } = config; workspaces.forEach((one, index) => { console.log(`${index + 1} element of ${workspaces.length} elements, workspaceId:${one.workspaceId}`); if (one.creatorSystemUserId == null) { const workspaceSystemUsers = db.workspaceSystemUsers.find({ workspaceId: one.workspaceId }).sort({ _id: -1 }).toArray(); const [firstUser] = workspaceSystemUsers; if (!firstUser) { console.log(`not found workspace owner for workspaceId:${one.workspaceId}`); // return; } else { one.creatorSystemUserId = firstUser.systemUserId; } } const workspaceRoles = db.roles.find({ 'assignments.ids': one.workspaceId }).toArray(); if (!workspaceRoles.length) { console.log(`not found workspace roles for workspaceId:${one.workspaceId}`); return; } const creatorWorkspaceRoleIds = workspaceRoles.filter(role => role.parentRoleId != null && roles.workspace.creatorRoleId.value === role.parentRoleId.value).map(item => item.roleId); const invitationRoleIds = workspaceRoles.filter(role => role.parentRoleId != null && roles.workspace.invitationIds.map(item => item.value).includes(role.parentRoleId.value)).map(item => item.roleId); const { count } = db.identitycounters.findOneAndUpdate({ model: 'rawMessages' }, { $inc: { count: 1 } }, { returnNewDocument: true }); const payload = { rawMessageId: count, rawMessage: { ...event.rawMessage, data: { ...event.rawMessage.data, creatorSystemUserId: one.creatorSystemUserId || null, "creatorWorkspaceRoleIds" : creatorWorkspaceRoleIds, "creatorSystemUserEmail" : null, "invitationRoleIds" : invitationRoleIds, "conditions" : [ ] }, "workspaceId" : one.workspaceId, }, }; // console.log('payload', payload); db.rawMessages.insert(payload); }); ```