add license by users

This commit is contained in:
Alexander.Trofimov
2017-11-21 17:51:20 +03:00
parent e2a59a6713
commit f1f7b93ed3
3 changed files with 139 additions and 89 deletions

View File

@ -59,10 +59,12 @@ exports.LICENSE_RESULT = {
UnknownUser : 4,
Connections : 5,
ExpiredTrial: 6,
SuccessLimit: 7
SuccessLimit: 7,
UsersCount : 8
};
exports.LICENSE_CONNECTIONS = 20;
exports.LICENSE_EXPIRE_USERS_ONE_DAY = 24 * 60 * 60; // day in seconds
exports.AVS_OFFICESTUDIO_FILE_UNKNOWN = 0x0000;
exports.AVS_OFFICESTUDIO_FILE_DOCUMENT = 0x0040;
@ -184,6 +186,7 @@ exports.REDIS_KEY_PUBSUB = 'pubsub';
exports.REDIS_KEY_SAVE_LOCK = 'savelock:';
exports.REDIS_KEY_PRESENCE_HASH = 'presence:hash:';
exports.REDIS_KEY_PRESENCE_SET = 'presence:set:';
exports.REDIS_KEY_PRESENCE_UNIQUE_USERS = 'presence:unique:users';
exports.REDIS_KEY_LOCKS = 'locks:';
exports.REDIS_KEY_CHANGES_INDEX = 'changesindex:';
exports.REDIS_KEY_LOCK_DOCUMENT = 'lockdocument:';

View File

@ -53,7 +53,7 @@ const redisKeyLicense = cfgRedisPrefix + ((constants.PACKAGE_TYPE_OS === oPackag
exports.readLicense = function*() {
const c_LR = constants.LICENSE_RESULT;
const c_LM = constants.LICENSE_MODE;
const resMax = {count: 999999, type: c_LR.Success, mode: c_LM.None, connections: 999999999};
const resMax = {count: 999999, type: c_LR.Success, mode: c_LM.None, connections: 999999999, users: 999999999};
const res = {
count: 1,
type: c_LR.Error,
@ -61,7 +61,9 @@ exports.readLicense = function*() {
packageType: oPackageType,
mode: c_LM.None,
branding: false,
connections: constants.LICENSE_CONNECTIONS
connections: constants.LICENSE_CONNECTIONS,
usersCount: 0,
usersExpire: constants.LICENSE_EXPIRE_USERS_ONE_DAY
};
let checkFile = false;
try {
@ -92,6 +94,13 @@ exports.readLicense = function*() {
if (oLicense.hasOwnProperty('connections')) {
res.connections = oLicense['connections'] >> 0;
}
if (oLicense.hasOwnProperty('users_count')) {
res.usersCount = oLicense['users_count'] >> 0;
}
if (oLicense.hasOwnProperty('users_expire')) {
res.usersExpire = Math.max(constants.LICENSE_EXPIRE_USERS_ONE_DAY, (oLicense['users_expire'] >> 0) *
constants.LICENSE_EXPIRE_USERS_ONE_DAY);
}
} else {
throw 'verify';
}

View File

@ -152,6 +152,7 @@ const redisKeyForceSave = cfgRedisPrefix + constants.REDIS_KEY_FORCE_SAVE;
const redisKeyForceSaveTimer = cfgRedisPrefix + constants.REDIS_KEY_FORCE_SAVE_TIMER;
const redisKeyForceSaveTimerLock = cfgRedisPrefix + constants.REDIS_KEY_FORCE_SAVE_TIMER_LOCK;
const redisKeySaved = cfgRedisPrefix + constants.REDIS_KEY_SAVED;
const redisKeyPresenceUniqueUsers = cfgRedisPrefix + constants.REDIS_KEY_PRESENCE_UNIQUE_USERS;
const EditorTypes = {
document : 0,
@ -471,7 +472,7 @@ function getConnectionInfo(conn) {
return JSON.stringify(data);
}
function updatePresenceCommandsToArray(outCommands, docId, userId, userInfo) {
var expireAt = new Date().getTime() + cfgExpPresence * 1000;
const expireAt = new Date().getTime() + cfgExpPresence * 1000;
outCommands.push(
['zadd', redisKeyPresenceSet + docId, expireAt, userId],
['hset', redisKeyPresenceHash + docId, userId, userInfo],
@ -480,13 +481,20 @@ function updatePresenceCommandsToArray(outCommands, docId, userId, userInfo) {
);
}
function* updatePresence(docId, userId, connInfo) {
var multi = redisClient.multi(getUpdatePresenceCommands(docId, userId, connInfo));
const multi = redisClient.multi(getUpdatePresenceCommands(docId, userId, connInfo));
yield utils.promiseRedis(multi, multi.exec);
}
function* updateEditUsers(userId) {
if (!licenseInfo.usersCount) {
return;
}
const expireAt = new Date().getTime() + licenseInfo.usersExpire * 1000;
yield utils.promiseRedis(redisClient, redisClient.zadd, redisKeyPresenceUniqueUsers, expireAt, userId);
}
function getUpdatePresenceCommands(docId, userId, connInfo) {
let commands = [];
const commands = [];
updatePresenceCommandsToArray(commands, docId, userId, connInfo);
var expireAt = new Date().getTime() + cfgExpPresence * 1000;
const expireAt = new Date().getTime() + cfgExpPresence * 1000;
commands.push(['zadd', redisKeyDocuments, expireAt, docId]);
return commands;
}
@ -1882,6 +1890,15 @@ exports.install = function(server, callbackFunction) {
conn.sessionTimeLastAction = new Date().getTime() - data.sessionTimeIdle;
}
if (!conn.user.view) {
let res = yield* _checkLicenseAuth(conn.user.idOriginal);
if (c_LR.Success !== res && c_LR.SuccessLimit !== res) {
conn.user.view = true;
} else {
yield* updateEditUsers(conn.user.idOriginal);
}
}
// Ситуация, когда пользователь уже отключен от совместного редактирования
if (bIsRestore && data.isCloseCoAuthoring) {
conn.sessionId = data.sessionId;//restore old
@ -2512,89 +2529,110 @@ exports.install = function(server, callbackFunction) {
return {res: !isLock, documentLocks: documentLocks};
}
function _checkLicense(conn) {
return co(function* () {
try {
const c_LR = constants.LICENSE_RESULT;
let licenseType = licenseInfo.type;
// Warning. Cluster version or if workers > 1 will work with increasing numbers.
let connectionsCount = 0;
if (constants.PACKAGE_TYPE_OS === licenseInfo.packageType && c_LR.Error === licenseType) {
connectionsCount = constants.LICENSE_CONNECTIONS;
} else if (c_LR.Success === licenseType) {
connectionsCount = licenseInfo.connections;
}
if (connectionsCount) {
const editConnectionsCount = (_.filter(connections, function (el) {
return true !== el.isCloseCoAuthoring && el.user.view !== true;
})).length;
licenseType = (connectionsCount > editConnectionsCount) ? c_LR.Success : c_LR.Connections;
function _checkLicense(conn) {
return co(function* () {
try {
const c_LR = constants.LICENSE_RESULT;
let licenseType = licenseInfo.type;
if (constants.PACKAGE_TYPE_OS === licenseInfo.packageType && c_LR.Error === licenseType) {
licenseType = c_LR.Success;
}
let rights = constants.RIGHTS.Edit;
if (config.get('server.edit_singleton')) {
// ToDo docId from url ?
const docIdParsed = urlParse.exec(conn.url);
if (docIdParsed && 1 < docIdParsed.length) {
const participantsMap = yield* getParticipantMap(docIdParsed[1]);
for (let i = 0; i < participantsMap.length; ++i) {
const elem = participantsMap[i];
if (!elem.view) {
rights = constants.RIGHTS.View;
break;
}
}
}
}
sendData(conn, {
type: 'license', license: {
type: licenseType,
light: licenseInfo.light,
mode: licenseInfo.mode,
rights: rights,
buildVersion: commonDefines.buildVersion,
buildNumber: commonDefines.buildNumber,
branding: licenseInfo.branding
}
});
} catch (err) {
logger.error('_checkLicense error:\r\n%s', err.stack);
}
});
}
function* _checkLicenseAuth(userId) {
const c_LR = constants.LICENSE_RESULT;
let licenseType = licenseInfo.type;
if (licenseInfo.usersCount) {
if (c_LR.Success === licenseType) {
const usersCount = yield utils.promiseRedis(redisClient, redisClient.zcount,
redisKeyPresenceUniqueUsers, '-inf', '+inf');
if (licenseInfo.usersCount > usersCount) {
licenseType = c_LR.Success;
} else {
let rank = yield utils.promiseRedis(redisClient, redisClient.zrank, redisKeyPresenceUniqueUsers,
userId);
licenseType = null !== rank ? c_LR.Success : c_LR.UsersCount;
}
}
} else {
// Warning. Cluster version or if workers > 1 will work with increasing numbers.
let connectionsCount = 0;
if (constants.PACKAGE_TYPE_OS === licenseInfo.packageType && c_LR.Error === licenseType) {
connectionsCount = constants.LICENSE_CONNECTIONS;
} else if (c_LR.Success === licenseType) {
connectionsCount = licenseInfo.connections;
}
if (connectionsCount) {
const editConnectionsCount = (_.filter(connections, function (el) {
return true !== el.isCloseCoAuthoring && el.user.view !== true;
})).length;
licenseType = (connectionsCount > editConnectionsCount) ? c_LR.Success : c_LR.Connections;
}
/*if (constants.PACKAGE_TYPE_OS === licenseInfo.packageType && c_LR.Error === licenseType) {
licenseType = c_LR.SuccessLimit;
const count = constants.LICENSE_CONNECTIONS;
let cursor = '0', sum = 0, scanRes, tmp, length, i, users;
while (true) {
scanRes = yield utils.promiseRedis(redisClient, redisClient.scan, cursor, 'MATCH', redisKeyPresenceHash + '*');
tmp = scanRes[1];
sum += (length = tmp.length);
for (i = 0; i < length; ++i) {
if (sum >= count) {
licenseType = c_LR.Connections;
break;
}
users = yield utils.promiseRedis(redisClient, redisClient.hlen, tmp[i]);
sum += users - (0 !== users ? 1 : 0);
}
if (sum >= count) {
licenseType = c_LR.Connections;
break;
}
cursor = scanRes[0];
if ('0' === cursor) {
break;
}
}
}*/
}
/*if (constants.PACKAGE_TYPE_OS === licenseInfo.packageType && c_LR.Error === licenseType) {
licenseType = c_LR.SuccessLimit;
const count = constants.LICENSE_CONNECTIONS;
let cursor = '0', sum = 0, scanRes, tmp, length, i, users;
while (true) {
scanRes = yield utils.promiseRedis(redisClient, redisClient.scan, cursor, 'MATCH', redisKeyPresenceHash + '*');
tmp = scanRes[1];
sum += (length = tmp.length);
for (i = 0; i < length; ++i) {
if (sum >= count) {
licenseType = c_LR.Connections;
break;
}
users = yield utils.promiseRedis(redisClient, redisClient.hlen, tmp[i]);
sum += users - (0 !== users ? 1 : 0);
}
if (sum >= count) {
licenseType = c_LR.Connections;
break;
}
cursor = scanRes[0];
if ('0' === cursor) {
break;
}
}
}*/
let rights = constants.RIGHTS.Edit;
if (config.get('server.edit_singleton')) {
// ToDo docId from url ?
const docIdParsed = urlParse.exec(conn.url);
if (docIdParsed && 1 < docIdParsed.length) {
const participantsMap = yield* getParticipantMap(docIdParsed[1]);
for (let i = 0; i < participantsMap.length; ++i) {
const elem = participantsMap[i];
if (!elem.view) {
rights = constants.RIGHTS.View;
break;
}
}
}
}
sendData(conn, {
type: 'license',
license: {
type: licenseType,
light: licenseInfo.light,
mode: licenseInfo.mode,
rights: rights,
buildVersion: commonDefines.buildVersion,
buildNumber: commonDefines.buildNumber,
branding: licenseInfo.branding
}
});
} catch (err) {
logger.error('_checkLicense error:\r\n%s', err.stack);
}
});
}
return licenseType;
}
sockjs_echo.installHandlers(server, {prefix: '/doc/['+constants.DOC_ID_PATTERN+']*/c', log: function(severity, message) {
//TODO: handle severity