ACS changes in prep for checking from ie content servers such as NNTP

* ACS now takes subject { client, user }
* ACS checks now consider client/user optional & checks fail (return false) if an object is not available
This commit is contained in:
Bryan Ashby 2018-12-28 10:39:41 -07:00
parent 8d46a305c5
commit 046550842b
4 changed files with 124 additions and 44 deletions

View File

@ -10,15 +10,15 @@ const assert = require('assert');
const _ = require('lodash'); const _ = require('lodash');
class ACS { class ACS {
constructor(client) { constructor(subject) {
this.client = client; this.subject = subject;
} }
check(acs, scope, defaultAcs) { check(acs, scope, defaultAcs) {
acs = acs ? acs[scope] : defaultAcs; acs = acs ? acs[scope] : defaultAcs;
acs = acs || defaultAcs; acs = acs || defaultAcs;
try { try {
return checkAcs(acs, { client : this.client } ); return checkAcs(acs, { subject : this.subject } );
} catch(e) { } catch(e) {
Log.warn( { exception : e, acs : acs }, 'Exception caught checking ACS'); Log.warn( { exception : e, acs : acs }, 'Exception caught checking ACS');
return false; return false;
@ -57,7 +57,7 @@ class ACS {
return true; // no ACS check req. return true; // no ACS check req.
} }
try { try {
return checkAcs(acs, { client : this.client } ); return checkAcs(acs, { subject : this.subject } );
} catch(e) { } catch(e) {
Log.warn( { exception : e, acs : acs }, 'Exception caught checking ACS'); Log.warn( { exception : e, acs : acs }, 'Exception caught checking ACS');
return false; return false;
@ -75,7 +75,7 @@ class ACS {
const matchCond = condArray.find( cond => { const matchCond = condArray.find( cond => {
if(_.has(cond, 'acs')) { if(_.has(cond, 'acs')) {
try { try {
return checkAcs(cond.acs, { client : this.client } ); return checkAcs(cond.acs, { subject : this.subject } );
} catch(e) { } catch(e) {
Log.warn( { exception : e, acs : cond }, 'Exception caught checking ACS'); Log.warn( { exception : e, acs : cond }, 'Exception caught checking ACS');
return false; return false;

View File

@ -844,32 +844,36 @@ function peg$parse(input, options) {
} }
const client = options.client;
const user = options.client.user;
const UserProps = require('./user_property.js'); const UserProps = require('./user_property.js');
const Log = require('./logger.js').log;
const _ = require('lodash');
const moment = require('moment'); const moment = require('moment');
const client = _.get(options, 'subject.client');
const user = _.get(options, 'subject.user');
function checkAccess(acsCode, value) { function checkAccess(acsCode, value) {
try { try {
return { return {
LC : function isLocalConnection() { LC : function isLocalConnection() {
return client.isLocal(); return client && client.isLocal();
}, },
AG : function ageGreaterOrEqualThan() { AG : function ageGreaterOrEqualThan() {
return !isNaN(value) && user.getAge() >= value; return !isNaN(value) && user && user.getAge() >= value;
}, },
AS : function accountStatus() { AS : function accountStatus() {
if(!user) {
return false;
}
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
value = [ value ]; value = [ value ];
} }
const userAccountStatus = user.getPropertyAsNumber(UserProps.AccountStatus); const userAccountStatus = user.getPropertyAsNumber(UserProps.AccountStatus);
return value.map(n => parseInt(n, 10)).includes(userAccountStatus); return value.map(n => parseInt(n, 10)).includes(userAccountStatus);
}, },
EC : function isEncoding() { EC : function isEncoding() {
const encoding = client.term.outputEncoding.toLowerCase(); const encoding = _.get(client, 'term.outputEncoding', '').toLowerCase();
switch(value) { switch(value) {
case 0 : return 'cp437' === encoding; case 0 : return 'cp437' === encoding;
case 1 : return 'utf-8' === encoding; case 1 : return 'utf-8' === encoding;
@ -877,27 +881,41 @@ function peg$parse(input, options) {
} }
}, },
GM : function isOneOfGroups() { GM : function isOneOfGroups() {
if(!user) {
return false;
}
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
return false; return false;
} }
return value.some(groupName => user.isGroupMember(groupName)); return value.some(groupName => user.isGroupMember(groupName));
}, },
NN : function isNode() { NN : function isNode() {
if(!client) {
return false;
}
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
value = [ value ]; value = [ value ];
} }
return value.map(n => parseInt(n, 10)).includes(client.node); return value.map(n => parseInt(n, 10)).includes(client.node);
}, },
NP : function numberOfPosts() { NP : function numberOfPosts() {
if(!user) {
return false;
}
const postCount = user.getPropertyAsNumber(UserProps.PostCount) || 0; const postCount = user.getPropertyAsNumber(UserProps.PostCount) || 0;
return !isNaN(value) && postCount >= value; return !isNaN(value) && postCount >= value;
}, },
NC : function numberOfCalls() { NC : function numberOfCalls() {
if(!user) {
return false;
}
const loginCount = user.getPropertyAsNumber(UserProps.LoginCount); const loginCount = user.getPropertyAsNumber(UserProps.LoginCount);
return !isNaN(value) && loginCount >= value; return !isNaN(value) && loginCount >= value;
}, },
AA : function accountAge() { AA : function accountAge() {
if(!user) {
return false;
}
const accountCreated = moment(user.getProperty(UserProps.AccountCreated)); const accountCreated = moment(user.getProperty(UserProps.AccountCreated));
const now = moment(); const now = moment();
const daysOld = accountCreated.diff(moment(), 'days'); const daysOld = accountCreated.diff(moment(), 'days');
@ -907,78 +925,98 @@ function peg$parse(input, options) {
daysOld >= value; daysOld >= value;
}, },
BU : function bytesUploaded() { BU : function bytesUploaded() {
if(!user) {
return false;
}
const bytesUp = user.getPropertyAsNumber(UserProps.FileUlTotalBytes) || 0; const bytesUp = user.getPropertyAsNumber(UserProps.FileUlTotalBytes) || 0;
return !isNaN(value) && bytesUp >= value; return !isNaN(value) && bytesUp >= value;
}, },
UP : function uploads() { UP : function uploads() {
if(!user) {
return false;
}
const uls = user.getPropertyAsNumber(UserProps.FileUlTotalCount) || 0; const uls = user.getPropertyAsNumber(UserProps.FileUlTotalCount) || 0;
return !isNaN(value) && uls >= value; return !isNaN(value) && uls >= value;
}, },
BD : function bytesDownloaded() { BD : function bytesDownloaded() {
if(!user) {
return false;
}
const bytesDown = user.getPropertyAsNumber(UserProps.FileDlTotalBytes) || 0; const bytesDown = user.getPropertyAsNumber(UserProps.FileDlTotalBytes) || 0;
return !isNaN(value) && bytesDown >= value; return !isNaN(value) && bytesDown >= value;
}, },
DL : function downloads() { DL : function downloads() {
if(!user) {
return false;
}
const dls = user.getPropertyAsNumber(UserProps.FileDlTotalCount) || 0; const dls = user.getPropertyAsNumber(UserProps.FileDlTotalCount) || 0;
return !isNaN(value) && dls >= value; return !isNaN(value) && dls >= value;
}, },
NR : function uploadDownloadRatioGreaterThan() { NR : function uploadDownloadRatioGreaterThan() {
if(!user) {
return false;
}
const ulCount = user.getPropertyAsNumber(UserProps.FileUlTotalCount) || 0; const ulCount = user.getPropertyAsNumber(UserProps.FileUlTotalCount) || 0;
const dlCount = user.getPropertyAsNumber(UserProps.FileDlTotalCount) || 0; const dlCount = user.getPropertyAsNumber(UserProps.FileDlTotalCount) || 0;
const ratio = ~~((ulCount / dlCount) * 100); const ratio = ~~((ulCount / dlCount) * 100);
return !isNaN(value) && ratio >= value; return !isNaN(value) && ratio >= value;
}, },
KR : function uploadDownloadByteRatioGreaterThan() { KR : function uploadDownloadByteRatioGreaterThan() {
if(!user) {
return false;
}
const ulBytes = user.getPropertyAsNumber(UserProps.FileUlTotalBytes) || 0; const ulBytes = user.getPropertyAsNumber(UserProps.FileUlTotalBytes) || 0;
const dlBytes = user.getPropertyAsNumber(UserProps.FileDlTotalBytes) || 0; const dlBytes = user.getPropertyAsNumber(UserProps.FileDlTotalBytes) || 0;
const ratio = ~~((ulBytes / dlBytes) * 100); const ratio = ~~((ulBytes / dlBytes) * 100);
return !isNaN(value) && ratio >= value; return !isNaN(value) && ratio >= value;
}, },
PC : function postCallRatio() { PC : function postCallRatio() {
if(!user) {
return false;
}
const postCount = user.getPropertyAsNumber(UserProps.PostCount) || 0; const postCount = user.getPropertyAsNumber(UserProps.PostCount) || 0;
const loginCount = user.getPropertyAsNumber(UserProps.LoginCount) || 0; const loginCount = user.getPropertyAsNumber(UserProps.LoginCount) || 0;
const ratio = ~~((postCount / loginCount) * 100); const ratio = ~~((postCount / loginCount) * 100);
return !isNaN(value) && ratio >= value; return !isNaN(value) && ratio >= value;
}, },
SC : function isSecureConnection() { SC : function isSecureConnection() {
return client.session.isSecure; return _.get(client, 'session.isSecure', false);
}, },
ML : function minutesLeft() { ML : function minutesLeft() {
// :TODO: implement me! // :TODO: implement me!
return false; return false;
}, },
TH : function termHeight() { TH : function termHeight() {
return !isNaN(value) && client.term.termHeight >= value; return !isNaN(value) && _.get(client, 'term.termHeight', 0) >= value;
}, },
TM : function isOneOfThemes() { TM : function isOneOfThemes() {
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
return false; return false;
} }
return value.includes(_.get(client, 'currentTheme.name'));
return value.includes(client.currentTheme.name);
}, },
TT : function isOneOfTermTypes() { TT : function isOneOfTermTypes() {
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
return false; return false;
} }
return value.includes(_.get(client, 'term.termType'));
return value.includes(client.term.termType);
}, },
TW : function termWidth() { TW : function termWidth() {
return !isNaN(value) && client.term.termWidth >= value; return !isNaN(value) && _.get(client, 'term.termWidth', 0) >= value;
}, },
ID : function isUserId(value) { ID : function isUserId(value) {
if(!user) {
return false;
}
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
value = [ value ]; value = [ value ];
} }
return value.map(n => parseInt(n, 10)).includes(user.userId); return value.map(n => parseInt(n, 10)).includes(user.userId);
}, },
WD : function isOneOfDayOfWeek() { WD : function isOneOfDayOfWeek() {
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
value = [ value ]; value = [ value ];
} }
return value.map(n => parseInt(n, 10)).includes(new Date().getDay()); return value.map(n => parseInt(n, 10)).includes(new Date().getDay());
}, },
MM : function isMinutesPastMidnight() { MM : function isMinutesPastMidnight() {
@ -989,7 +1027,9 @@ function peg$parse(input, options) {
} }
}[acsCode](value); }[acsCode](value);
} catch (e) { } catch (e) {
client.log.warn( { acsCode : acsCode, value : value }, 'Invalid ACS string!'); const logger = _.get(client, 'log', Log);
logger.warn( { acsCode : acsCode, value : value }, 'Invalid ACS string!');
return false; return false;
} }
} }

View File

@ -85,7 +85,7 @@ function Client(/*input, output*/) {
this.currentTheme = { info : { name : 'N/A', description : 'None' } }; this.currentTheme = { info : { name : 'N/A', description : 'None' } };
this.lastKeyPressMs = Date.now(); this.lastKeyPressMs = Date.now();
this.menuStack = new MenuStack(this); this.menuStack = new MenuStack(this);
this.acs = new ACS(this); this.acs = new ACS( { client : this, user : this.user } );
this.mciCache = {}; this.mciCache = {};
this.interruptQueue = new UserInterruptQueue(this); this.interruptQueue = new UserInterruptQueue(this);

View File

@ -1,31 +1,35 @@
{ {
const client = options.client;
const user = options.client.user;
const UserProps = require('./user_property.js'); const UserProps = require('./user_property.js');
const Log = require('./logger.js').log;
const _ = require('lodash');
const moment = require('moment'); const moment = require('moment');
const client = _.get(options, 'subject.client');
const user = _.get(options, 'subject.user');
function checkAccess(acsCode, value) { function checkAccess(acsCode, value) {
try { try {
return { return {
LC : function isLocalConnection() { LC : function isLocalConnection() {
return client.isLocal(); return client && client.isLocal();
}, },
AG : function ageGreaterOrEqualThan() { AG : function ageGreaterOrEqualThan() {
return !isNaN(value) && user.getAge() >= value; return !isNaN(value) && user && user.getAge() >= value;
}, },
AS : function accountStatus() { AS : function accountStatus() {
if(!user) {
return false;
}
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
value = [ value ]; value = [ value ];
} }
const userAccountStatus = user.getPropertyAsNumber(UserProps.AccountStatus); const userAccountStatus = user.getPropertyAsNumber(UserProps.AccountStatus);
return value.map(n => parseInt(n, 10)).includes(userAccountStatus); return value.map(n => parseInt(n, 10)).includes(userAccountStatus);
}, },
EC : function isEncoding() { EC : function isEncoding() {
const encoding = client.term.outputEncoding.toLowerCase(); const encoding = _.get(client, 'term.outputEncoding', '').toLowerCase();
switch(value) { switch(value) {
case 0 : return 'cp437' === encoding; case 0 : return 'cp437' === encoding;
case 1 : return 'utf-8' === encoding; case 1 : return 'utf-8' === encoding;
@ -33,27 +37,41 @@
} }
}, },
GM : function isOneOfGroups() { GM : function isOneOfGroups() {
if(!user) {
return false;
}
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
return false; return false;
} }
return value.some(groupName => user.isGroupMember(groupName)); return value.some(groupName => user.isGroupMember(groupName));
}, },
NN : function isNode() { NN : function isNode() {
if(!client) {
return false;
}
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
value = [ value ]; value = [ value ];
} }
return value.map(n => parseInt(n, 10)).includes(client.node); return value.map(n => parseInt(n, 10)).includes(client.node);
}, },
NP : function numberOfPosts() { NP : function numberOfPosts() {
if(!user) {
return false;
}
const postCount = user.getPropertyAsNumber(UserProps.PostCount) || 0; const postCount = user.getPropertyAsNumber(UserProps.PostCount) || 0;
return !isNaN(value) && postCount >= value; return !isNaN(value) && postCount >= value;
}, },
NC : function numberOfCalls() { NC : function numberOfCalls() {
if(!user) {
return false;
}
const loginCount = user.getPropertyAsNumber(UserProps.LoginCount); const loginCount = user.getPropertyAsNumber(UserProps.LoginCount);
return !isNaN(value) && loginCount >= value; return !isNaN(value) && loginCount >= value;
}, },
AA : function accountAge() { AA : function accountAge() {
if(!user) {
return false;
}
const accountCreated = moment(user.getProperty(UserProps.AccountCreated)); const accountCreated = moment(user.getProperty(UserProps.AccountCreated));
const now = moment(); const now = moment();
const daysOld = accountCreated.diff(moment(), 'days'); const daysOld = accountCreated.diff(moment(), 'days');
@ -63,78 +81,98 @@
daysOld >= value; daysOld >= value;
}, },
BU : function bytesUploaded() { BU : function bytesUploaded() {
if(!user) {
return false;
}
const bytesUp = user.getPropertyAsNumber(UserProps.FileUlTotalBytes) || 0; const bytesUp = user.getPropertyAsNumber(UserProps.FileUlTotalBytes) || 0;
return !isNaN(value) && bytesUp >= value; return !isNaN(value) && bytesUp >= value;
}, },
UP : function uploads() { UP : function uploads() {
if(!user) {
return false;
}
const uls = user.getPropertyAsNumber(UserProps.FileUlTotalCount) || 0; const uls = user.getPropertyAsNumber(UserProps.FileUlTotalCount) || 0;
return !isNaN(value) && uls >= value; return !isNaN(value) && uls >= value;
}, },
BD : function bytesDownloaded() { BD : function bytesDownloaded() {
if(!user) {
return false;
}
const bytesDown = user.getPropertyAsNumber(UserProps.FileDlTotalBytes) || 0; const bytesDown = user.getPropertyAsNumber(UserProps.FileDlTotalBytes) || 0;
return !isNaN(value) && bytesDown >= value; return !isNaN(value) && bytesDown >= value;
}, },
DL : function downloads() { DL : function downloads() {
if(!user) {
return false;
}
const dls = user.getPropertyAsNumber(UserProps.FileDlTotalCount) || 0; const dls = user.getPropertyAsNumber(UserProps.FileDlTotalCount) || 0;
return !isNaN(value) && dls >= value; return !isNaN(value) && dls >= value;
}, },
NR : function uploadDownloadRatioGreaterThan() { NR : function uploadDownloadRatioGreaterThan() {
if(!user) {
return false;
}
const ulCount = user.getPropertyAsNumber(UserProps.FileUlTotalCount) || 0; const ulCount = user.getPropertyAsNumber(UserProps.FileUlTotalCount) || 0;
const dlCount = user.getPropertyAsNumber(UserProps.FileDlTotalCount) || 0; const dlCount = user.getPropertyAsNumber(UserProps.FileDlTotalCount) || 0;
const ratio = ~~((ulCount / dlCount) * 100); const ratio = ~~((ulCount / dlCount) * 100);
return !isNaN(value) && ratio >= value; return !isNaN(value) && ratio >= value;
}, },
KR : function uploadDownloadByteRatioGreaterThan() { KR : function uploadDownloadByteRatioGreaterThan() {
if(!user) {
return false;
}
const ulBytes = user.getPropertyAsNumber(UserProps.FileUlTotalBytes) || 0; const ulBytes = user.getPropertyAsNumber(UserProps.FileUlTotalBytes) || 0;
const dlBytes = user.getPropertyAsNumber(UserProps.FileDlTotalBytes) || 0; const dlBytes = user.getPropertyAsNumber(UserProps.FileDlTotalBytes) || 0;
const ratio = ~~((ulBytes / dlBytes) * 100); const ratio = ~~((ulBytes / dlBytes) * 100);
return !isNaN(value) && ratio >= value; return !isNaN(value) && ratio >= value;
}, },
PC : function postCallRatio() { PC : function postCallRatio() {
if(!user) {
return false;
}
const postCount = user.getPropertyAsNumber(UserProps.PostCount) || 0; const postCount = user.getPropertyAsNumber(UserProps.PostCount) || 0;
const loginCount = user.getPropertyAsNumber(UserProps.LoginCount) || 0; const loginCount = user.getPropertyAsNumber(UserProps.LoginCount) || 0;
const ratio = ~~((postCount / loginCount) * 100); const ratio = ~~((postCount / loginCount) * 100);
return !isNaN(value) && ratio >= value; return !isNaN(value) && ratio >= value;
}, },
SC : function isSecureConnection() { SC : function isSecureConnection() {
return client.session.isSecure; return _.get(client, 'session.isSecure', false);
}, },
ML : function minutesLeft() { ML : function minutesLeft() {
// :TODO: implement me! // :TODO: implement me!
return false; return false;
}, },
TH : function termHeight() { TH : function termHeight() {
return !isNaN(value) && client.term.termHeight >= value; return !isNaN(value) && _.get(client, 'term.termHeight', 0) >= value;
}, },
TM : function isOneOfThemes() { TM : function isOneOfThemes() {
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
return false; return false;
} }
return value.includes(_.get(client, 'currentTheme.name'));
return value.includes(client.currentTheme.name);
}, },
TT : function isOneOfTermTypes() { TT : function isOneOfTermTypes() {
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
return false; return false;
} }
return value.includes(_.get(client, 'term.termType'));
return value.includes(client.term.termType);
}, },
TW : function termWidth() { TW : function termWidth() {
return !isNaN(value) && client.term.termWidth >= value; return !isNaN(value) && _.get(client, 'term.termWidth', 0) >= value;
}, },
ID : function isUserId(value) { ID : function isUserId(value) {
if(!user) {
return false;
}
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
value = [ value ]; value = [ value ];
} }
return value.map(n => parseInt(n, 10)).includes(user.userId); return value.map(n => parseInt(n, 10)).includes(user.userId);
}, },
WD : function isOneOfDayOfWeek() { WD : function isOneOfDayOfWeek() {
if(!Array.isArray(value)) { if(!Array.isArray(value)) {
value = [ value ]; value = [ value ];
} }
return value.map(n => parseInt(n, 10)).includes(new Date().getDay()); return value.map(n => parseInt(n, 10)).includes(new Date().getDay());
}, },
MM : function isMinutesPastMidnight() { MM : function isMinutesPastMidnight() {
@ -145,7 +183,9 @@
} }
}[acsCode](value); }[acsCode](value);
} catch (e) { } catch (e) {
client.log.warn( { acsCode : acsCode, value : value }, 'Invalid ACS string!'); const logger = _.get(client, 'log', Log);
logger.warn( { acsCode : acsCode, value : value }, 'Invalid ACS string!');
return false; return false;
} }
} }