You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
5.9 KiB

var jwt = require('jsonwebtoken');
var deprecate = require('deprecate');
var _ = require('underscore')
require('string.prototype.startswith');
var taskRouterUrlBase = 'https://taskrouter.twilio.com';
var taskRouterVersion = 'v1';
var eventUrlBase = 'https://event-bridge.twilio.com/v1/wschannels';
function TaskRouterCapability(accountSid, authToken, workspaceSid, channelId) {
this.accountSid = accountSid;
this.authToken = authToken;
this.policies = [];
this.workspaceSid = workspaceSid;
this.channelId = channelId;
this._baseUrl = taskRouterUrlBase + '/' + taskRouterVersion + '/Workspaces/' + this.workspaceSid;
this._validateJWT();
this._setupResource();
var eventsUrl = eventUrlBase + '/' + this.accountSid + '/' + channelId;
// add permissions to GET and POST to the event-bridge channel
this.allow(eventsUrl, 'GET');
this.allow(eventsUrl, 'POST');
// add permission to fetch the instance resource
this.allow(this._resourceUrl, 'GET');
}
TaskRouterCapability.prototype._setupResource = function() {
if(this.channelId.startsWith('WS')) {
this._resourceUrl = this._baseUrl;
}else if(this.channelId.startsWith('WK')) {
this._resourceUrl = this._baseUrl + '/Workers/' + this.channelId;
var activityUrl = this._baseUrl + '/Activities';
this.allow(activityUrl, "GET");
var tasksUrl = this._baseUrl + '/Tasks/**';
this.allow(tasksUrl, "GET");
var workerReservationsUrl = this._resourceUrl + '/Reservations/**';
this.allow(workerReservationsUrl, "GET");
}else if(this.channelId.startsWith('WQ')) {
this._resourceUrl = this._baseUrl + '/TaskQueues/' + this.channelId;
}
}
TaskRouterCapability.prototype._validateJWT = function() {
if(!this.accountSid || !this.accountSid.startsWith('AC')) {
throw "Invalid AccountSid provided: "+this.accountSid;
}
if(!this.workspaceSid || !this.workspaceSid.startsWith('WS')) {
throw "Invalid WorkspaceSid provided: "+this.workspaceSid;
}
if(!this.channelId) {
throw "ChannelId not provided";
}
var prefix = this.channelId.substring(0,2);
if(prefix != 'WS' && prefix != 'WK' && prefix != 'WQ') {
throw "Invalid ChannelId provided: "+this.channelId;
}
}
TaskRouterCapability.prototype.allowFetchSubresources = function() {
this.allow(this._resourceUrl+'/**', 'GET');
}
TaskRouterCapability.prototype.allowUpdates = function() {
this.allow(this._resourceUrl, 'POST');
}
TaskRouterCapability.prototype.allowUpdatesSubresources = function() {
this.allow(this._resourceUrl+'/**', 'POST');
}
TaskRouterCapability.prototype.allowDelete = function() {
this.allow(this._resourceUrl, 'DELETE');
}
TaskRouterCapability.prototype.allowDeleteSubresources = function() {
this.allow(this._resourceUrl+'/**', 'DELETE');
}
TaskRouterCapability.prototype.allowDeleteSubresources = function() {
this.allow(this._resourceUrl+'/**', 'DELETE');
}
TaskRouterCapability.prototype.allowWorkerActivityUpdates = function() {
if(this.channelId.startsWith('WK')) {
deprecate('allowWorkerActivityUpdates is deprecated. Please use TaskRouterWorkerCapability.allowWorkerActivityUpdates() instead');
this.allow(this._resourceUrl, 'POST', {}, {"ActivitySid": {'required': true}});
}else {
throw "Deprecated function not applicable to non Worker";
}
}
TaskRouterCapability.prototype.allowWorkerFetchAttributes = function() {
if(this.channelId.startsWith('WK')) {
deprecate('allowWorkerFetchAttributes is deprecated. Please use TaskRouterWorkerCapability; added automatically in constructor');
this.allow(this._resourceUrl, 'GET');
}else {
throw "Deprecated function not applicable to non Worker";
}
}
TaskRouterCapability.prototype.allowTaskReservationUpdates = function() {
if(this.channelId.startsWith('WK')) {
deprecate('allowTaskReservationUpdates is deprecated. Please use TaskRouterWorkerCapability.allowReservationUpdates() instead');
this.allow(this._baseUrl + "/Tasks/**", "POST");
}else {
throw "Deprecated function not applicable to non Worker";
}
}
TaskRouterCapability.prototype.addPolicy = function(url, method, allowed, queryFilter, postFilter) {
var policy = {
url: url,
method: method
};
if (queryFilter) {
policy.query_filter = queryFilter;
} else {
policy.query_filter = {};
}
if (postFilter) {
policy.post_filter = postFilter;
} else {
policy.post_filter = {};
}
if (typeof allowed !== 'undefined') {
policy.allow = allowed;
} else {
policy.allow = true;
}
this.policies.push(policy);
}
TaskRouterCapability.prototype.allow = function(url, method, queryFilter, postFilter) {
this.addPolicy(url, method, true, queryFilter, postFilter);
}
TaskRouterCapability.prototype.deny = function(url, method, queryFilter, postFilter) {
this.addPolicy(url, method, false, queryFilter, postFilter);
}
TaskRouterCapability.prototype.generate = function(ttl) {
var taskRouterAttributes = {
'account_sid': this.accountSid,
'channel': this.channelId,
'workspace_sid': this.workspaceSid
}
if(this.channelId.startsWith('WK')) {
taskRouterAttributes.worker_sid = this.channelId;
}else if(this.channelId.startsWith('WQ')) {
taskRouterAttributes.taskqueue_sid = this.channelId;
}
return this._generate(ttl, taskRouterAttributes);
}
TaskRouterCapability.prototype._generate = function(ttl, extraAttributes) {
var payload = {
iss: this.accountSid,
exp: (Math.floor(new Date() / 1000) + (ttl || 3600)),
version: taskRouterVersion,
friendly_name: this.channelId,
policies: this.policies,
};
_.extend(payload, extraAttributes);
return jwt.sign(payload, this.authToken);
}
module.exports = TaskRouterCapability;