diff --git a/Common/config/default.json b/Common/config/default.json index 4cd62b7e..c17283ee 100644 --- a/Common/config/default.json +++ b/Common/config/default.json @@ -56,8 +56,6 @@ "limits_image_size": 26214400, "limits_image_download_timeout": 120, "editor_settings_spellchecker_url": "/spellchecker", - "license_activeconnections_tracking_interval": 300, - "license_activeconnections_tracking_cleanupperiods": 2, "default_license_file_path": "./../../", "default_license_file_name": "./license.lic" }, diff --git a/Common/sources/commondefines.js b/Common/sources/commondefines.js index 7b124aa8..2c065382 100644 --- a/Common/sources/commondefines.js +++ b/Common/sources/commondefines.js @@ -383,11 +383,6 @@ TaskQueueData.prototype = { } }; -function ErrorWithResult() { - this.errorCode = constants.NO_ERROR; - this.data = null; -} - function OutputSfcData() { this['key'] = undefined; this['status'] = undefined; @@ -573,7 +568,6 @@ var c_oAscCodePageUtf8 = 46;//65001 exports.TaskQueueData = TaskQueueData; exports.CMailMergeSendData = CMailMergeSendData; exports.InputCommand = InputCommand; -exports.ErrorWithResult = ErrorWithResult; exports.OutputSfcData = OutputSfcData; exports.OutputMailMerge = OutputMailMerge; exports.c_oAscCsvDelimiter = c_oAscCsvDelimiter; diff --git a/Common/sources/constants.js b/Common/sources/constants.js index b92e99ef..d2d665c7 100644 --- a/Common/sources/constants.js +++ b/Common/sources/constants.js @@ -101,13 +101,6 @@ exports.VKEY_KEY_EXPIRE = -122; exports.VKEY_USER_COUNT_EXCEED = -123; exports.VKEY_TIME_EXPIRE = -124; exports.VKEY_TIME_INCORRECT = -125; -exports.LICENSE_ERROR = -140; -exports.LICENSE_ERROR_TYPE = -141; -exports.LICENSE_ERROR_ARGUMENT = -142; -exports.LICENSE_ERROR_PERMISSION = -143; -exports.LICENSE_ERROR_ACTIVE_CONNECTION_QUOTA_EXCEED = -144; -exports.LICENSE_ERROR_INVALID_DATE = -145; -exports.LICENSE_ERROR_FILE = -146; exports.EDITOR_CHANGES = -160; exports.QUEUE_PRIORITY_LOW = 0; diff --git a/DocService/package.json b/DocService/package.json index f9a4d720..24b9ac86 100644 --- a/DocService/package.json +++ b/DocService/package.json @@ -16,7 +16,6 @@ "pg": "4.4.0", "redis": "^0.12.1", "sockjs": "http://d2ettrnqo7v976.cloudfront.net/npm/sockjs-node/v0.3.15.14.tar.gz", - "underscore": "1.8.3", - "xml2js": "^0.4.12" + "underscore": "1.8.3" } } diff --git a/DocService/sources/DocsCoServer.js b/DocService/sources/DocsCoServer.js index 49bb5bae..4bcbbd62 100644 --- a/DocService/sources/DocsCoServer.js +++ b/DocService/sources/DocsCoServer.js @@ -101,7 +101,8 @@ var PublishType = { changes : 5, auth : 6, receiveTask : 7, - warning: 8 + warning: 8, + cursor: 9 }; var EditorTypes = { @@ -383,6 +384,9 @@ function sendDataWarning(conn, msg) { function sendDataMessage(conn, msg) { sendData(conn, {type: "message", messages: msg}); } +function sendDataCursor(conn, msg) { + sendData(conn, {type: "cursor", messages: msg}); +} function sendReleaseLock(conn, userLocks) { sendData(conn, {type: "releaseLock", locks: _.map(userLocks, function(e) { return { @@ -776,6 +780,9 @@ exports.install = function(server, callbackFunction) { case 'message' : yield* onMessage(conn, data); break; + case 'cursor' : + yield* onCursor(conn, data); + break; case 'getLock' : yield* getLock(conn, data, false); break; @@ -1429,6 +1436,17 @@ exports.install = function(server, callbackFunction) { yield* publish({type: PublishType.message, docId: docId, userId: userId, messages: messages}, docId, userId); } + function* onCursor(conn, data) { + var docId = conn.docId; + var userId = conn.user.id; + var msg = {cursor: data.cursor, time: Date.now(), user: userId, username: conn.user.name}; + + logger.info("send cursor: docId = %s %s", docId, msg); + + var messages = [msg]; + yield* publish({type: PublishType.cursor, docId: docId, userId: userId, messages: messages}, docId, userId); + } + function* getLock(conn, data, bIsRestore) { logger.info("getLock docid: %s", conn.docId); var fLock = null; @@ -1938,6 +1956,12 @@ exports.install = function(server, callbackFunction) { sendDataWarning(participant, data.description); }); break; + case PublishType.cursor: + participants = getParticipants(true, data.docId, data.userId); + _.each(participants, function(participant) { + sendDataCursor(participant, data.messages); + }); + break; } } catch (err) { logger.debug('pubsub message error:\r\n%s', err.stack); diff --git a/DocService/sources/licensereader.js b/DocService/sources/licensereader.js deleted file mode 100644 index 8d96bc30..00000000 --- a/DocService/sources/licensereader.js +++ /dev/null @@ -1,905 +0,0 @@ -var fs = require('fs'); -var crypto = require("crypto"); -var utils = require('./../../Common/sources/utils'); -var xmlParseString = require('xml2js').parseString; -var logger = require('./../../Common/sources/logger'); -var configCoAuthoring = require('config').get('services.CoAuthoring'); -var config_server = configCoAuthoring.get('server'); -var commonDefines = require('./../../Common/sources/commondefines'); -var constants = require('./../../Common/sources/constants'); - -var cfgActiveConnectionsTrackingCleanupPeriods = config_server.get('license_activeconnections_tracking_cleanupperiods'); -var cfgActiveConnectionsTrackingInterval = config_server.get('license_activeconnections_tracking_interval'); - -var redis = require(configCoAuthoring.get('redis.name')); -var cfgRedisPrefix = configCoAuthoring.get('redis.prefix'); -var cfgRedisHost = configCoAuthoring.get('redis.host'); -var cfgRedisPort = configCoAuthoring.get('redis.port'); -var redisKeyLicense = cfgRedisPrefix + 'license'; - -var redisClient = redis.createClient(cfgRedisPort, cfgRedisHost, {}); -redisClient.on('error', function(err) { - logger.error('redisClient error:\r\n%s', err.stack); -}); - -function extendClass (Child, Parent) { - var F = function() { }; - F.prototype = Parent.prototype; - Child.prototype = new F(); - Child.prototype.constructor = Child; - Child.superclass = Parent.prototype; -} - -var Key = new Buffer([127, 61, 35, 56, 57, 12, 30, 62, 21, 76, 33, 0, 95, 81, 1, 14, 6, 91, 15, 26, 30, 16, 22, 0, 32, 36, 115, 21, 12, 2, 42, 17, 67, 111, 96, 38, 33, 81, 55, 30, 80, 33, 97, 21, 27, 51, 52, 0, 15, 82, 45, 69, 18, 61, 33, 7, 35, 59, 21, 90, 120, 53, 58, 3, 79, 119, 8, 92, 37, 74, 59, 3, 6, 60, 26, 39, 101, 4, 87, 35, 2, 25, 89, 14, 16, 105, 20, 40, 7, 54, 56, 95, 30, 1, 58, 22, 28, 36, 82, 2, 37, 48, 19, 95, 42, 12, 7, 97, 82, 0, 39, 67, 98, 28, 48, 3, 49, 63, 57, 72, 49, 43, 58, 4, 22, 49, 22, 55, 94, 50, 11, 25, 48, 27, 81, 37, 95, 53, 65, 24, 15, 11, 94, 35, 21, 42, 95, 41, 88, 40, 89, 25, 53, 95, 92, 72, 125, 29, 95, 37, 16, 70, 89, 0, 21, 20, 40, 54, 1, 28, 53, 120, 13, 0, 56, 55, 33, 94, 41, 1, 91, 116, 109, 84, 88, 59, 40, 24, 40, 84, 55, 87, 6, 107, 23, 36, 41, 30, 70, 27, 15, 35, 61, 2, 70, 15, 23, 44, 26, 81, 39, 64, 52, 79, 69, 39, 68, 20, 12, 65, 26, 86, 24, 76, 25, 2, 63, 52, 30, 24, 37, 87, 108, 50, 46, 27, 102, 89, 114, 4, 67, 25, 32, 45, 10, 7, 50, 48, 87, 121, 22, 6, 35, 40, 17, 80, 85, 124, 15, 2, 30, 20, 20, 30, 52, 42, 68, 22, 50, 35, 13, 10, 36, 20, 50, 66, 12, 33, 88, 28, 108, 44, 24, 62, 19, 101, 14, 85, 33, 53, 52, 73, 37, 85, 49, 43, 68, 32, 14, 81, 94, 38, 41, 68, 8, 16, 16, 43, 30, 48, 73, 54, 23, 8, 10, 32, 18, 47, 1, 41, 41, 1, 76, 16, 121, 57, 58, 16, 7, 80, 51, 56, 5, 30, 21, 63, 13, 50, 60, 65, 33, 32, 38, 107, 14, 8, 5, 15, 56, 70, 37, 45, 63, 82, 53, 4, 2, 33, 45, 37, 13, 1, 91, 62, 80, 19, 28, 110, 33, 3, 68, 39, 5, 18, 27, 74, 79, 101, 42, 21, 28, 11, 23, 24, 17, 90, 111, 18, 46, 50, 69, 93, 44, 31, 24, 27, 78, 49, 11, 21, 83, 112, 78, 48, 125, 34, 36, 8, 87, 118, 32, 0, 25, 69, 108]); - -function symmetricDecrypt(data) { - var decipher = crypto.createDecipheriv('aes-256-cbc', Key.slice(0, 32/*256/8*/), Key.slice(0, 16/*128/8*/)); - var result = decipher.update(data, null, 'utf8'); - result += decipher.final('utf8'); - return result; -} - -function promiseXmlParseString(xmlDoc) { - return new Promise(function(resolve, reject) { - xmlParseString(xmlDoc, function(err, result) { - if (err) { - reject(err); - } else { - resolve(result); - } - }); - }); -} - -var LicenseType = { - NoValidation: 0, // no validation - ByVKey: 1, // pure saas scheme - ByTimeUsage: 4, // counts the time of usage of the editor - ByDocumentSessions: 5, // counts sessions of editing - OpenSource: 6, - ByActiveConnectionsAWS: 8, // active connections (editing) only on AWS Instance - ByUserCount: 2, // number of users limitation - ByActiveConnections: 3, // active connections (editing) - ByUserCount2: 7 // number of users limitation -}; -var EditorPermissions = { - PERMISSION_NONE: 0, // 0000 - PERMISSION_WRITER: 1, // 0001 - PERMISSION_SPREADSHEET: 2, // 0010 - PERMISSION_PRESENTATION: 4, // 0100 - PERMISSION_ALL: 1 | 2 | 4 -}; - -function LicenseReaderBase() { - this._id = ''; - - this._license_type = ''; - this._path = ''; - - this._startDate = null; - this._endDate = null; - this._endDateThreshold = null; - - this._customer = ''; - this._customer_id = ''; - this._customer_addr = ''; - this._customer_www = ''; - this._customer_mail = ''; - this._customer_info = ''; - this._customer_logo = ''; - - this._correct = false; - this._found = false; - - this._can_co_authoring = false; - this._can_branding = false; - - this._permissions = EditorPermissions.PERMISSION_NONE; - - this._user_data = ''; -} -LicenseReaderBase.prototype._fillMembersBase = function(xmlDocObj) { - var res = false; - try { - var startElem = xmlDocObj['root']['teamlaboffice'][0]; - if (startElem) { - this._startDate = startElem.hasOwnProperty('startdate') ? new Date(startElem['startdate'][0]) : null; - this._endDate = startElem.hasOwnProperty('enddate') ? new Date(startElem['enddate'][0]) : null; - this._id = startElem.hasOwnProperty('id') ? startElem['id'][0] : ''; - - if (null === this._startDate || null === this._endDate || null === this._id) { - return false; - } - - this._endDateThreshold = startElem.hasOwnProperty('enddatethreshold') ? new Date(startElem['enddatethreshold'][0]) : null; - this._customer = startElem.hasOwnProperty('customer') ? startElem['customer'][0] : ''; - this._customer_id = startElem.hasOwnProperty('customer_id') ? startElem['customer_id'][0] : ''; - this._customer_addr = startElem.hasOwnProperty('customer_addr') ? startElem['customer_addr'][0] : ''; - this._customer_www = startElem.hasOwnProperty('customer_www') ? startElem['customer_www'][0] : ''; - this._customer_mail = startElem.hasOwnProperty('customer_mail') ? startElem['customer_mail'][0] : ''; - this._customer_info = startElem.hasOwnProperty('customer_info') ? startElem['customer_info'][0] : ''; - this._customer_logo = startElem.hasOwnProperty('customer_logo') ? startElem['customer_logo'][0] : ''; - this._license_type = startElem.hasOwnProperty('lictype') ? startElem['lictype'][0] : ''; - this._can_co_authoring = startElem.hasOwnProperty('can_co_authoring') ? ('true' === startElem['can_co_authoring'][0].toLowerCase()) : ''; - this._can_branding = startElem.hasOwnProperty('can_branding') ? ('true' === startElem['can_branding'][0].toLowerCase()) : ''; - this._user_data = startElem.hasOwnProperty('user_data') ? startElem['user_data'][0] : ''; - - if (startElem.hasOwnProperty('permissions')) { - var permissions = startElem['permissions'][0].toLowerCase(); - this._permissions |= -1 !== permissions.indexOf('w') ? EditorPermissions.PERMISSION_WRITER : EditorPermissions.PERMISSION_NONE; - this._permissions |= -1 !== permissions.indexOf('e') ? EditorPermissions.PERMISSION_SPREADSHEET : EditorPermissions.PERMISSION_NONE; - this._permissions |= -1 !== permissions.indexOf('p') ? EditorPermissions.PERMISSION_PRESENTATION : EditorPermissions.PERMISSION_NONE; - } else { - this._permissions = EditorPermissions.PERMISSION_NONE; - } - - if (null === this._endDateThreshold) { - this._endDateThreshold = new Date(this._endDate); - this._endDateThreshold.setMonth(this._endDateThreshold.getMonth() + 1); - } - - res = true; - } - } catch (e) { - logger.error('error init:\r\n%s', e.stack); - } - return res && this.fillMembers(xmlDocObj); -}; -LicenseReaderBase.prototype.fillMembers = function(xmlDocObj) { - return true; -}; -LicenseReaderBase.prototype.read = function*(path) { - try { - this._path = path; - var xmlDoc = symmetricDecrypt(fs.readFileSync(this._path)); - this._found = true; - - if (this._fillMembersBase(yield promiseXmlParseString(xmlDoc))) { - this._correct = true; - } - } catch (e) { - logger.error('error init:\r\n%s', e.stack); - } -}; -LicenseReaderBase.prototype.getStartDate = function() { - return this._startDate; -}; -LicenseReaderBase.prototype.getEndDate = function() { - return this._endDate; -}; -LicenseReaderBase.prototype.getEndDateThreshold = function() { - return this._endDateThreshold; -}; -LicenseReaderBase.prototype.getId = function() { - return this._id; -}; -LicenseReaderBase.prototype.getCustomer = function() { - return this._customer; -}; -LicenseReaderBase.prototype.getCustomerId = function() { - return this._customer_id; -}; -LicenseReaderBase.prototype.getCustomerAddr = function() { - return this._customer_addr; -}; -LicenseReaderBase.prototype.getCustomerWww = function() { - return this._customer_www; -}; -LicenseReaderBase.prototype.getCustomerMail = function(){ - return this._customer_mail; -}; -LicenseReaderBase.prototype.getCustomerInfo = function(){ - return this._customer_info; -}; -LicenseReaderBase.prototype.getCustomerLogo = function(){ - return this._customer_logo; -}; -LicenseReaderBase.prototype.getUserData = function(){ - return this._user_data; -}; -LicenseReaderBase.prototype.isLicenseFound = function(){ - return this._found; -}; -LicenseReaderBase.prototype.isLicenseCorrect = function(){ - return this._correct; -}; -LicenseReaderBase.prototype.getPermissions = function(){ - return this._permissions; -}; -LicenseReaderBase.prototype.getCanCoAuthoring = function(){ - return this._can_co_authoring; -}; -LicenseReaderBase.prototype.getCanBranding = function(){ - return this._can_branding; -}; - -function ActiveConnectionsLicenseReaderSingle() { - ActiveConnectionsLicenseReaderSingle.superclass.constructor.apply(this, arguments); - this._quota = 0; -} -extendClass(ActiveConnectionsLicenseReaderSingle, LicenseReaderBase); -ActiveConnectionsLicenseReaderSingle.prototype.fillMembers = function(xmlDocObj) { - var res = false; - try { - var startElem = xmlDocObj['root']['teamlaboffice'][0]; - if (startElem) { - this._quota = startElem.hasOwnProperty('connectionquota') ? (startElem['connectionquota'][0]>>0) : null; - res = true; - } - } catch (e) { - logger.error('error init:\r\n%s', e.stack); - } - return res; -}; -ActiveConnectionsLicenseReaderSingle.prototype.getUserQuota = function() { - return this._quota; -}; - -function ActiveConnectionsLicenseReader() { - this._licenses = []; - this._correct = false; -} -ActiveConnectionsLicenseReader.prototype.createSingleFileReader = function*(path) { - var res = new ActiveConnectionsLicenseReaderSingle(); - yield* res.read(path); - return res; -}; -ActiveConnectionsLicenseReader.prototype.read = function*(path) { - var files = yield* getLicenseFiles(path); - for (var i = 0; i < files.length; ++i) { - var item = yield* this.createSingleFileReader(files[i]); - if (item.isLicenseFound() && item.isLicenseCorrect()) { - this._licenses.push(item); - } - } - this._correct = (0 < this._licenses.length); -}; -ActiveConnectionsLicenseReader.prototype.getLicensesByTime = function(useThreshold) { - var time = new Date(); - var res = [], item, startTime, endTime, endTimeThreshold; - for (var i = 0; i < this._licenses.length; ++i) { - item = this._licenses[i]; - startTime = item.getStartDate(); - endTime = item.getEndDate(); - endTimeThreshold = item.getEndDateThreshold(); - if ((startTime <= time) && (useThreshold ? (time <= endTimeThreshold) : (time <= endTime))) { - res.push(item); - } - } - return res; -}; -ActiveConnectionsLicenseReader.prototype.getStartDate = function() { - if (!this.isLicenseCorrect()) - return null; - var minDate = this._licenses[0].getStartDate(), startDate; - for (var i = 1; i < this._licenses.length; ++i) { - startDate = this._licenses[i].getStartDate(); - - if (minDate > startDate) - minDate = startDate; - } - return minDate; -}; -ActiveConnectionsLicenseReader.prototype.getEndDate = function() { - if (!this.isLicenseCorrect()) - return null; - var maxDate = this._licenses[0].getEndDate(), endDate; - for (var i = 1; i < this._licenses.length; ++i) { - endDate = this._licenses[i].getEndDate(); - - if (maxDate < endDate) - maxDate = endDate; - } - return maxDate; -}; -ActiveConnectionsLicenseReader.prototype.getEndDateThreshold = function() { - if (!this.isLicenseCorrect()) - return null; - var thresholdDate = this._licenses[0].getEndDateThreshold(), endDateThreshold; - for (var i = 1; i < this._licenses.length; ++i) { - endDateThreshold = this._licenses[i].getEndDateThreshold(); - - if (thresholdDate < endDateThreshold) - thresholdDate = endDateThreshold; - } - return thresholdDate; -}; -ActiveConnectionsLicenseReader.prototype.getId = function() { - var res = null; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getId(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getCustomer = function() { - var res = null; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getCustomer(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getCustomerId = function() { - var res = null; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getCustomerId(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getCustomerAddr = function() { - var res = null; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getCustomerAddr(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getCustomerWww = function() { - var res = null; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getCustomerWww(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getCustomerMail = function() { - var res = null; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getCustomerMail(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getCustomerInfo = function() { - var res = null; - - var licenses = this.getLicensesByTime(false); - if (0 < licenses.length) { - res = licenses[0].getCustomerInfo(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getCustomerLogo = function() { - var res = null; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getCustomerLogo(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getUserData = function() { - var res = null; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getUserData(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.isLicenseFound = function() { - return this._correct; -}; -ActiveConnectionsLicenseReader.prototype.isLicenseCorrect = function() { - return this._correct; -}; -ActiveConnectionsLicenseReader.prototype.getUserQuota = function() { - var res = false; - var bHasLicense = false; - - var licenses = this.getLicensesByTime(true); - for (var i = 0; i < licenses.length; ++i) { - res += licenses[i].getUserQuota(); - bHasLicense = true; - } - if (!bHasLicense) { - res = 100000; // no limit connections (limit coAuthoring = false) - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getCanCoAuthoring = function() { - var res = false; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getCanCoAuthoring(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getCanBranding = function() { - var res = false; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getCanBranding(); - } - - return res; -}; -ActiveConnectionsLicenseReader.prototype.getPermissions = function() { - var res = EditorPermissions.PERMISSION_NONE; - - var licenses = this.getLicensesByTime(true); - if (0 < licenses.length) { - res = licenses[0].getPermissions(); - } - - return res; -}; - -function LicenseMetaData() { - this.vkey = ''; - this.docId = ''; - this.userId = ''; - this.checkIP = false; - this.currentIP = ''; - this.editorId = -1; -} -LicenseMetaData.prototype.init = function(vkey, docId, userId, editorId) { - this.vkey = vkey; - - this.docId = docId; - if (null == this.docId || '' === this.docId) - this.docId = 'doc'; - - this.userId = userId; - if (null == this.userId || '' === this.userId) - this.userId = 'usr'; - - this.editorId = editorId; -}; -function LicenseRights(bIsAllEnabled) { - this.canOpen = true; - this.canSave = true; - this.canCoAuthoring = false; - this.canExport = true; - this.canPrint = true; - this.canBranding = false; - if (bIsAllEnabled) { - this.enableAll(); - } -} -LicenseRights.prototype.enableAll = function() { - this.canOpen = true; - this.canSave = true; - this.canCoAuthoring = true; - this.canExport = true; - this.canPrint = true; - this.canBranding = true; -}; - -function BaseTrackingInfo() { - this.oLastCleanupTime = new Date(); - - this.license = null; -} -BaseTrackingInfo.prototype.setLicense = function(license) { - this.license = license; -}; -BaseTrackingInfo.prototype.getLicense = function() { - return this.license; -}; -BaseTrackingInfo.prototype.getActiveUserCount = function*() { - return yield utils.promiseRedis(redisClient, redisClient.hlen, redisKeyLicense); -}; -BaseTrackingInfo.prototype.track = function*(userId, docId, isAlive) { - if (null == userId) { - userId = ''; - } - if (null == docId) { - docId = ''; - } - - var key = userId + docId; - if ('' === key) { - key = 'empty'; - } - - var now = new Date(); - if (!isAlive) { - // inactive - yield* this.cleanup(); - } else { - // active - yield utils.promiseRedis(redisClient, redisClient.hset, redisKeyLicense, key, now.getTime()); - } - - // make cleanup (once per day) - yield* this.checkCleanUp(now); -}; -BaseTrackingInfo.prototype.isQuotaExceed = function*(userId, docId) { - // no license, no quota - if (null === this.license) { - return false; - } - - if (null == userId) { - userId = ''; - } - if (null == docId) { - docId = ''; - } - - var count = yield* this.getActiveUserCount(); - // ok anyway - if (count < this.license.getUserQuota()) { - return false; - } - - // quota is exeeded. try to find this user/document in active or inactive list - var key = userId + docId; - if ('' === key) { - key = 'empty'; - } - - if (yield utils.promiseRedis(redisClient, redisClient.hexists, redisKeyLicense, key)) { - return false; - } - - // the quota is exceeded - return true; -}; -BaseTrackingInfo.prototype.isLicenseFileValid = function() { - return (null != this.license - && this.license.isLicenseFound() - && this.license.isLicenseCorrect()); -}; -BaseTrackingInfo.prototype.isLicenseDateValid = function() { - if (!this.license) { - return false; - } - var now = new Date(); - - var start = this.license.getStartDate(); - var end = this.license.getEndDate(); - return (start < now && end > now); -}; -BaseTrackingInfo.prototype.isLicenseEndDateGreater = function(time) { - if (!this.license) { - return false; - } - var end = this.license.getEndDate(); - return end > time; -}; -BaseTrackingInfo.prototype.isLicenseDateThresholdExpired = function() { - if (!this.license) { - return true; - } - var now = new Date(); - var threshold = this.license.getEndDateThreshold(); - - return now > threshold; -}; -BaseTrackingInfo.prototype.getPermissions = function() { - return this.license ? this.license.getPermissions() : EditorPermissions.PERMISSION_NONE; -}; -BaseTrackingInfo.prototype.checkCleanUp = function*(now) { - if (!now) { - now = new Date(); - } - now.setDate(now.getDate() - 1); - if (now > this.oLastCleanupTime) { - yield* this.cleanup(); - this.oLastCleanupTime = now; - } -}; -BaseTrackingInfo.prototype.removeByTime = function*(time) { - logger.debug('removeByTime fields'); - var oAllFields = yield utils.promiseRedis(redisClient, redisClient.hgetall, redisKeyLicense); - var arrToRemove = []; - if (oAllFields) { - for (var i in oAllFields) if (oAllFields.hasOwnProperty(i)) { - if ((oAllFields[i] >> 0) <= time) - arrToRemove.push(i); - } - if (0 < arrToRemove.length) { - logger.debug(arrToRemove); - arrToRemove.unshift(redisClient, redisClient.hdel, redisKeyLicense); - yield utils.promiseRedis.apply(this, arrToRemove); - } - } -}; -BaseTrackingInfo.prototype.cleanup = function*() { - yield* this.removeByTime(Number.MAX_VALUE); -}; -BaseTrackingInfo.prototype.cleanupIfQuotaExceed = function*() { - yield* this.cleanup(); -}; - -function TrackingInfo() { - TrackingInfo.superclass.constructor.apply(this, arguments); - this.sdCleanupExpiredMinutes = 2.0; - - this._init(); -} -extendClass(TrackingInfo, BaseTrackingInfo); -TrackingInfo.prototype._init = function() { - var periods = cfgActiveConnectionsTrackingCleanupPeriods || 2; - var tracking_time = cfgActiveConnectionsTrackingInterval || 300; - this.sdCleanupExpiredMinutes = periods * tracking_time / 60.0; -}; -TrackingInfo.prototype.cleanup = function*() { - var active_count = yield* this.getActiveUserCount(); - var quota = (null === this.license) ? 2048 : this.license.getUserQuota(); - - if (active_count >= (quota - 1)) { - // cleanup active list - var date = new Date(); - date.setMinutes(date.getMinutes() - this.sdCleanupExpiredMinutes); - yield* this.removeByTime(date.getTime()); - } -}; - -function UserCount2TrackingInfo() { - UserCount2TrackingInfo.superclass.constructor.apply(this, arguments); -} -extendClass(UserCount2TrackingInfo, BaseTrackingInfo); -UserCount2TrackingInfo.prototype.track = function*(userId, docId, isAlive) { - // don't use "docId" in ths scheme, 'isAlive' flag must be ignored - return yield* UserCount2TrackingInfo.superclass.track.call(this, userId, null, true); -}; -UserCount2TrackingInfo.prototype.isQuotaExceed = function*(userId, docId) { - // don't use "docId" in ths scheme - return yield* UserCount2TrackingInfo.superclass.isQuotaExceed.call(this, userId, null); -}; -UserCount2TrackingInfo.prototype.cleanupIfQuotaExceed = function*() { - yield* UserCount2TrackingInfo.superclass.checkCleanUp.call(); -}; - -function VKeyLicenseInfo() { -} -VKeyLicenseInfo.prototype.getRights = function() { - // ToDo Affiliete - return new LicenseRights(true); -}; -VKeyLicenseInfo.prototype.read = function*(path) { -}; - -function ActiveConnectionLicenseInfo() { - this.m_dtBuildTime = new Date(); //ToDo возможно стоит от этого отказаться - - this.trackInfo = this.createTrackingInfo(); -} -ActiveConnectionLicenseInfo.prototype.read = function*(path) { - // set license reader - this.trackInfo.setLicense(yield* this.createLicenseReader(path)); -}; -ActiveConnectionLicenseInfo.prototype.createLicenseReader = function*(path) { - var res = new ActiveConnectionsLicenseReader(); - yield* res.read(path); - return res; -}; -ActiveConnectionLicenseInfo.prototype.createTrackingInfo = function() { - return new TrackingInfo(); -}; -ActiveConnectionLicenseInfo.prototype.track = function*(userId, docId, isAlive) { - yield* this.trackInfo.track(userId, docId, isAlive); -}; -ActiveConnectionLicenseInfo.prototype.getActiveUserCount = function*() { - return yield* this.trackInfo.getActiveUserCount(); -}; -ActiveConnectionLicenseInfo.prototype.getRights = function*(oLicenseMetaData) { - var result = new commonDefines.ErrorWithResult(); - var oRights = result.data = new LicenseRights(); - - if (!this.trackInfo.isLicenseFileValid()) { - result.errorCode = constants.LICENSE_ERROR_FILE; - - // we have to allow editing in demo mode - // we must verify only quota. - // don't verify dates, build time, editor permissions - - // check connections quota - if (yield* this.checkQuotaExceeded(oLicenseMetaData)) { - result.errorCode = constants.LICENSE_ERROR_ACTIVE_CONNECTION_QUOTA_EXCEED; - } else { - oRights.canSave = true; - oRights.canCoAuthoring = false; - oRights.canExport = true; - } - return result; - } - - // license file is valid, we have to work with license scheme - var bValidDate = false; - - // check dates - if (this.trackInfo.isLicenseDateValid()) { - // valid date - bValidDate = true; - } else { - // license dates are invalid, check threshold - - result.errorCode = constants.LICENSE_ERROR_INVALID_DATE; - - if (!this.trackInfo.isLicenseDateThresholdExpired()) { - bValidDate = true; - } - } - - // check build time (it must be lower than license end time) - var bBuildTimeValid = this.trackInfo.isLicenseEndDateGreater(this.m_dtBuildTime); - var bQuotaExceed = true; - var bEditorAllowed = false; - - var permissions = this.trackInfo.getPermissions(); - if (oLicenseMetaData.editorId === constants.EDITOR_TYPE_CONVERTATION - && permissions !== EditorPermissions.PERMISSION_NONE) { - // if ConvertService.ashx or FileUploader.ashx are used don't check quota - bQuotaExceed = false; - bEditorAllowed = true; - } else { - // check connections quota - bQuotaExceed = yield* this.checkQuotaExceeded(oLicenseMetaData); - if (bQuotaExceed) { - result.errorCode = constants.LICENSE_ERROR_ACTIVE_CONNECTION_QUOTA_EXCEED; - } - - // check editor id and permissions - if ((oLicenseMetaData.editorId === constants.EDITOR_TYPE_WORD && 0 !== (permissions & EditorPermissions.PERMISSION_WRITER)) - || (oLicenseMetaData.editorId === constants.EDITOR_TYPE_SPREADSHEET && 0 !== (permissions & EditorPermissions.PERMISSION_SPREADSHEET)) - || (oLicenseMetaData.editorId === constants.EDITOR_TYPE_PRESENTATION && 0 !== (permissions & EditorPermissions.PERMISSION_PRESENTATION))) { - // editor usage is allowed by license. - bEditorAllowed = true; - } else { - // editor usage is not allowed by license - } - } - - // set up rights - //oRights.CanBranding = oLicense.getCanBranding(); ToDo убрали взятие из лицензии. Теперь если есть лицензия, то разрешаем. Нет - без лицензии. - oRights.canBranding = true; - if (bValidDate && bEditorAllowed && !bQuotaExceed && bBuildTimeValid) { - oRights.canSave = true; - oRights.canExport = true; - oRights.canCoAuthoring = true; - } - return result; -}; -ActiveConnectionLicenseInfo.prototype.checkQuotaExceeded = function*(oLicenseMetaData) { - var userId = this.getUserId(oLicenseMetaData); - var documentId = this.getDocumentId(oLicenseMetaData); - var bQuotaExceed = yield* this.trackInfo.isQuotaExceed(userId, documentId); - - if (bQuotaExceed) { - // cleare lists of inactive users - yield* this.trackInfo.cleanupIfQuotaExceed(); - bQuotaExceed = yield* this.trackInfo.isQuotaExceed(userId, documentId); - } - - return bQuotaExceed; -}; -ActiveConnectionLicenseInfo.prototype.getUserId = function(oLicenseMetaData) { - return oLicenseMetaData.userId; -}; -ActiveConnectionLicenseInfo.prototype.getDocumentId = function(oLicenseMetaData) { - return oLicenseMetaData.docId; -}; - -function UserCountLicenseInfo() { - UserCountLicenseInfo.superclass.constructor.apply(this, arguments); -} -extendClass(UserCountLicenseInfo, ActiveConnectionLicenseInfo); -UserCountLicenseInfo.prototype.track = function*(userId, docId, isAlive) { - yield* this.trackInfo.track(userId, null, isAlive); -}; -ActiveConnectionLicenseInfo.prototype.getDocumentId = function(oLicenseMetaData) { - return ''; -}; - -function UserCount2LicenseInfo() { - UserCount2LicenseInfo.superclass.constructor.apply(this, arguments); -} -extendClass(UserCount2LicenseInfo, UserCountLicenseInfo); -UserCount2LicenseInfo.prototype.createTrackingInfo = function() { - return new UserCount2TrackingInfo(); -}; - -function MockLicenseInfo() { - // ToDo -} -function DocumentSessionLicenseInfo() { - // ToDo -} -function ActiveConnectionAWSLicenseInfo() { - // ToDo -} - -function* getLicenseFiles(path) { - var res = []; - try { - var files = yield utils.listObjects(path); - if (files) { - for (var i = 0; i < files.length; ++i) { - if (files[i].endsWith('.lic')) { - res.push(files[i]); - } - } - } - } catch (e) { - logger.error('error getLicenseFiles:\r\n%s', e.stack); - } - return res; -} -function* getLicenseSimple(path) { - var res = null; - var files = yield* getLicenseFiles(path); - if (0 < files.length) { - res = new LicenseReaderBase(); - yield* res.read(files[0]); - } - return res; -} -function* getLicenseType(path) { - var res = LicenseType.ByUserCount2; - var oLicSimple; - if ("VKEY" === path) { - res = LicenseType.ByVKey; - } else if (null !== (oLicSimple = yield* getLicenseSimple(path)) && oLicSimple.isLicenseFound() && oLicSimple.isLicenseCorrect()) { - if (oLicSimple._license_type === "ActiveConnections") - oLicenseType = LicenseType.ByActiveConnections; - else if (oLicSimple._license_type === "UserCount") - oLicenseType = LicenseType.ByUserCount; - else if (oLicSimple._license_type === "UserCount2") - oLicenseType = LicenseType.ByUserCount2; - else if (oLicSimple._license_type === "DocumentSessions") - oLicenseType = LicenseType.ByDocumentSessions; - else if (oLicSimple._license_type === "ActiveConnectionsAWS") - oLicenseType = LicenseType.ByActiveConnectionsAWS; - } - return res; -} - -function* createLicenseInfo(path) { - var lic = null; - var oLicType = yield* getLicenseType(path); - switch (oLicType) { - case LicenseType.ByVKey: // 1 - lic = new VKeyLicenseInfo(); - break; - case LicenseType.ByDocumentSessions: // 5 - lic = new DocumentSessionLicenseInfo(); - break; - case LicenseType.ByActiveConnectionsAWS: // 8 - lic = new ActiveConnectionAWSLicenseInfo(); - break; - case LicenseType.ByUserCount: // 2 - lic = new UserCountLicenseInfo(); - break; - case LicenseType.ByActiveConnections: // 3 - lic = new ActiveConnectionLicenseInfo(); - break; - case LicenseType.ByUserCount2: // 7 - default: - lic = new UserCount2LicenseInfo(); - break; - } - if (lic) { - yield* lic.read(path); - } - return lic; -} - -exports.createLicenseInfo = createLicenseInfo; -exports.getLicenseType = getLicenseType; -exports.LicenseType = LicenseType; -exports.LicenseMetaData = LicenseMetaData; \ No newline at end of file