Skip to content

Commit

Permalink
Merge pull request #4743 from Countly/cms-client
Browse files Browse the repository at this point in the history
[SER-974] Move CMS client to frontend
  • Loading branch information
kanwarujjaval authored Nov 29, 2023
2 parents 401a5ca + 92e84a6 commit 418632f
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 25 deletions.
92 changes: 89 additions & 3 deletions api/parts/mgmt/cms.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,17 @@ function transformAndStoreData(params, err, data, callback) {
}
else {
var transformedData = [];
for (let i = 0; i < data.length; i++) {
transformedData.push(Object.assign({_id: `${params.qstring._id}_${data[i].id}`, lu}, data[i].attributes));

if (params.dataTransformed) {
transformedData = data;
transformedData.forEach(item => {
item.lu = lu;
});
}
else {
for (let i = 0; i < data.length; i++) {
transformedData.push(Object.assign({_id: `${params.qstring._id}_${data[i].id}`, lu}, data[i].attributes));
}
}

var bulk = common.db.collection("cms_cache").initializeUnorderedBulkOp();
Expand Down Expand Up @@ -147,12 +156,29 @@ function syncCMSDataToDB(params) {
}
}

cmsApi.saveEntries = function(params) {
transformAndStoreData(
Object.assign({dataTransformed: true}, params),
null,
JSON.parse(params.qstring.entries),
function(err1) {
if (err1) {
log.e('An error occured while storing entries in DB: ' + err1);
common.returnMessage(params, 500, `Error occured when saving entries to DB: ${err1}`);
}
else {
common.returnMessage(params, 200, 'Entries saved');
}
});
};

/**
* Get entries for a given API ID
* Will request from CMS if entries are stale or not found
* @param {params} params - params object
* @returns {boolean} true
**/
cmsApi.getEntries = function(params) {
cmsApi.getEntriesWithUpdate = function(params) {

if (!params.qstring._id || AVAILABLE_API_IDS.indexOf(params.qstring._id) === -1) {
common.returnMessage(params, 400, 'Missing or incorrect API _id parameter');
Expand Down Expand Up @@ -231,6 +257,66 @@ cmsApi.getEntries = function(params) {
});
};

/**
* Get entries for a given API ID
* @param {params} params - params object
* @returns {boolean} true
**/
cmsApi.getEntries = function(params) {

if (!params.qstring._id || AVAILABLE_API_IDS.indexOf(params.qstring._id) === -1) {
common.returnMessage(params, 400, 'Missing or incorrect API _id parameter');
return false;
}

var query = { '_id': { '$regex': `^${params.qstring._id}` } };

try {
params.qstring.query = JSON.parse(params.qstring.query);
}
catch (ex) {
params.qstring.query = null;
}

if (params.qstring.query) {
query = {
$and: [
{ '_id': { '$regex': `^${params.qstring._id}` } },
{
$or: [
{ '_id': `${params.qstring._id}_meta` },
]
}
]
};
for (var cond in params.qstring.query) {
var condition = {};
condition[cond] = params.qstring.query[cond];
query.$and[1].$or.push(condition);
}
params.qstring.query = query;
}

common.db.collection('cms_cache').find(query).toArray(function(err, entries) {
if (err) {
common.returnMessage(params, 500, 'An error occured while fetching CMS entries from DB: ' + err);
return false;
}
let results = {data: entries || []};

// Remove meta entry
results.data = results.data.filter((item) => !item._id.endsWith('meta'));

// Special case for server-guide-config
if (params.qstring._id === 'server-guide-config' && results.data && results.data[0]) {
results.data[0].enableGuides = results.data[0].enableGuides || config.enableGuides;
}

common.returnOutput(params, results);
return true;
});
};

/**
* Clear cache for all API IDs
* @param {params} params - params object
Expand Down
8 changes: 8 additions & 0 deletions api/utils/requestProcessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -2865,6 +2865,14 @@ const processRequest = (params) => {

break;
}
case '/i/cms': {
switch (paths[3]) {
case 'save_entries':
validateUserForWrite(params, countlyApi.mgmt.cms.saveEntries);
break;
}
break;
}
default:
if (!plugins.dispatch(apiPath, {
params: params,
Expand Down
2 changes: 1 addition & 1 deletion frontend/express/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ Promise.all([plugins.dbConnection(countlyConfig), plugins.dbConnection("countly_
documentationLink: COUNTLY_DOCUMENTATION_LINK,
helpCenterLink: COUNTLY_HELPCENTER_LINK,
featureRequestLink: COUNTLY_FEATUREREQUEST_LINK,
}
},
};

var toDashboard = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

(function(countlyOnboarding) {

countlyCMS.fetchEntry('server-consents');
countlyCMS.fetchEntry('server-intro-video');
countlyCMS.fetchEntry('server-quick-start', { populate: true });

countlyOnboarding.generateAPIKey = function() {
var length = 40;
var text = [];
Expand Down Expand Up @@ -155,15 +151,15 @@
});
},
fetchIntroVideos: function(context) {
countlyCMS.fetchEntry('server-intro-video').then(function(resp) {
countlyCMS.fetchEntry('server-intro-video', { CMSFirst: true }).then(function(resp) {
context.commit('setIntroVideos', {
videoLinkForCE: resp.data[0].videoLinkForCE || '',
videoLinkForEE: resp.data[0].videoLinkForEE || '',
});
});
},
fetchConsentItems: function(context) {
countlyCMS.fetchEntry('server-consents').then(function(resp) {
countlyCMS.fetchEntry('server-consents', { CMSFirst: true }).then(function(resp) {
context.commit('setConsentItems', resp.data);
});
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@
var sessionCount = countlyGlobal.member.session_count || 0;
var isGlobalAdmin = countlyGlobal.member.global_admin;

countlyCMS.fetchEntry('server-quick-start', { populate: true }).then(function(resp) {
countlyCMS.fetchEntry('server-quick-start', { populate: true, CMSFirst: true }).then(function(resp) {
var isConsentPage = /initial-setup|initial-consent|not-responded-consent|not-subscribed-newsletter/.test(window.location.hash);
if (resp.data && resp.data.length && !isConsentPage) {
var showForNSessions = resp.data[0].showForNSessions;
Expand Down
183 changes: 169 additions & 14 deletions frontend/express/public/javascripts/countly/countly.cms.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,114 @@
/* global countlyCommon, jQuery */
/* global countlyCommon, countlyGlobal, jQuery */

// frontend client for fetching data from cms.count.ly

var AVAILABLE_API_IDS = ["server-guides", "server-consents", "server-intro-video", "server-quick-start", "server-guide-config"];
var CMS_TKN = "17fa74a2b4b1524e57e8790250f89f44f364fe567f13f4dbef02ef583e70dcdb700f87a6122212bb01ca6a14a8d4b85dc314296f71681988993c013ed2f6305b57b251af723830ea2aa180fc689af1052dd74bc3f4b9b35e5674d4214a8c79695face42057424f0494631679922a3bdaeb780b522bb025dfaea8d7d56a857dba";
var CMS_BASE_URL = "https://cms.count.ly/";
var UPDATE_INTERVAL = 2 * 60 * 60 * 1000; // 2 hours

(function(countlyCMS, $) {

countlyCMS.fetchEntry = function(entryID, options) {
var data = { _id: entryID };
if (options) {
if (options.populate) {
data.populate = options.populate;
}
if (options.query) {
data.query = JSON.stringify(options.query);
}
if (options.refresh) {
data.refresh = options.refresh;
}
var transformCMSResponse = function(response, params) {
var result = [];

response.forEach(function(item) {
result.push(Object.assign({_id: params._id + '_' + item.id, lu: Date.now()}, item.attributes));
});

return result;
};

var entryNeedsUpdate = function(entry) {
if ('lu' in entry) {
var diff = Date.now() - entry.lu;
return diff >= UPDATE_INTERVAL;
}

return true;
};

countlyCMS.requestFromCMS = function(params) {
var pageSize = 100;
var url = new URL('/api/' + params._id, CMS_BASE_URL);
var results = [];

var doRequest = function(pageNumber) {
url.searchParams.append('pagination[page]', pageNumber);
url.searchParams.append('pagination[pageSize]', pageSize);

if (params.populate) {
url.searchParams.append('populate', '*');
}

return new Promise(function(resolve, reject) {
$.ajax({
url: url.href,
headers: {
'Authorization': 'Bearer ' + CMS_TKN,
},
success: function(response) {
resolve(response);
},
error: function(xhr) {
reject(xhr.responseJSON);
},
});
});
};

var requestPage = function(pageNumber) {
return doRequest(pageNumber).then(function(response) {
var data = response.data;
var meta = response.meta;

if (data && data.length > 0 || data.id) {
results = results.concat(data);
}

if (meta && meta.pagination && meta.pagination.page < meta.pagination.pageCount) {
// Fetch next page
return requestPage(meta.pagination.page + 1);
}
else {
// All pages fetched or no pagination metadata, resolve
return Promise.resolve(results);
}
});
};

return requestPage(1);
};

countlyCMS.saveEntries = function(entryID, entries) {
var formData = new FormData();
formData.append('app_id', countlyCommon.ACTIVE_APP_ID);
formData.append('api_key', countlyGlobal.member.api_key);
formData.append('_id', entryID);
formData.append('entries', JSON.stringify(entries));

return new Promise(function(resolve, reject) {
$.ajax({
url: countlyCommon.API_PARTS.data.w + "/cms/save_entries",
method: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
resolve(response);
},
error: function(xhr) {
reject(xhr.responseJSON);
},
});
});
};

countlyCMS.requestFromBackend = function(params) {
return new Promise(function(resolve, reject) {
$.ajax({
url: countlyCommon.API_PARTS.data.r + "/cms/entries",
data: data,
data: params,
success: function(response) {
resolve(response);
},
Expand All @@ -31,6 +119,73 @@
});
};

countlyCMS.requestFromCMSAndSave = function(params) {
return new Promise(function(resolve, reject) {
countlyCMS.requestFromCMS(params)
.then(function(response) {
var transformedResponse = transformCMSResponse(response, params);

countlyCMS.saveEntries(params._id, transformedResponse);

resolve({data: transformedResponse});
})
.catch(function(err) {
reject(err);
});
});
};

countlyCMS.fetchEntry = function(entryID, options) {
if (!AVAILABLE_API_IDS.includes(entryID)) {
return Promise.reject({ result: 'Missing or incorrect API _id parameter'});
}

var params = {};
params._id = entryID;

if (options) {
if (options.populate) {
params.populate = options.populate;
}
if (options.query) {
params.query = JSON.stringify(options.query);
}
}

if (options && options.CMSFirst) {
// Request from cms first
return countlyCMS.requestFromCMSAndSave(params);
}
else {
// Request from backend first
return new Promise(function(resolve, reject) {
countlyCMS.requestFromBackend(params)
.then(function(response) {
// data found in backend
if (response.data && response.data.length > 0) {
// if data from backend is stale, get new data
if (entryNeedsUpdate(response.data[0]) || options.refresh) {
return countlyCMS.requestFromCMSAndSave(params);
}
else {
resolve(response);
}
}
else {
// data not found in backend, get from cms
return countlyCMS.requestFromCMSAndSave(params);
}
})
.then(function(response) {
resolve(response);
})
.catch(function(err) {
reject(err);
});
});
}
};

countlyCMS.clearCache = function(entryID) {
return new Promise(function(resolve, reject) {
$.ajax({
Expand Down

0 comments on commit 418632f

Please sign in to comment.