apps/strider/dist-lib/utils/user-socket.js
const gravatar = require('gravatar');
const models = require('../models');
const common = require('../common');
const jobs = require('../jobs');
const utils = require('../utils');
const Project = models.Project;
const User = models.User;
const Job = models.Job;
function UserSocket(userid) {
this.userid = userid;
this.sockets = [];
}
module.exports = UserSocket;
UserSocket.prototype = {
add: function (socket) {
const waiters = {};
const self = this;
for (const name in this.events) {
socket.on(name, (waiters[name] = waiter(socket, name)).handler);
}
this.getUser(function () {
for (const name in self.events) {
unWait(socket, waiters[name], self.events[name].bind(self));
}
});
this.sockets.push(socket);
},
remove: function (socket) {
const idx = this.sockets.indexOf(socket);
if (idx === -1)
return false;
this.sockets.splice(idx, 1);
return true;
},
/**
* Emit an even on all sockets
*/
emit: function (args) {
this.sockets.forEach(function (socket) {
socket.emit.apply(socket, args);
});
},
/**
* Apply handlers for all sockets
*/
on: function () {
this.sockets.forEach(function (socket) {
socket.on.apply(socket, arguments);
});
},
getUser: function (done) {
if (!this.userid)
return done();
const self = this;
User.findById(this.userid, function (err, user) {
if (err)
console.error('failed to get user - socket', err);
if (!user) {
console.error("user not found for the websocket - there's something strange going on w/ websocket auth. User Id: ", self.userid);
self.emit(['auth.failed']);
return;
}
self.user = user;
done();
});
},
events: {
'dashboard:jobs': function (done) {
jobs.latestJobs(this.user, function (err, jobs) {
done(jobs);
});
},
'dashboard:unknown': function (id, done) {
const user = this.user;
Job.findById(id)
.lean()
.exec(function (err, job) {
if (err || !job)
return console.error('[unknownjob] error getting job', id, err);
Project.findOne({ name: job.project.toLowerCase() })
.lean()
.exec(function (err, project) {
if (err || !project)
return console.error('[unknownjob] error getting project', id, err);
const njob = jobs.small(job);
njob.project = utils.sanitizeProject(project);
njob.project.access_level = User.projectAccessLevel(user, project);
// this will be filled in
njob.project.prev = [];
done(njob);
});
});
},
'build:job': function (id, done) {
const user = this.user;
Job.findById(id)
.lean()
.exec(function (err, job) {
if (err)
return console.error('Error retrieving job', id, err.message, err.stack);
if (!job)
return console.error('Job not found', id);
Project.findOne({ name: job.project.toLowerCase() })
.lean()
.exec(function (err, project) {
if (err || !project)
return console.error('Error getting project', job.project, err);
job.status = jobs.status(job);
job.project = utils.sanitizeProject(project);
job.project.access_level = User.projectAccessLevel(user, project);
job.project.prev = [];
done(job);
});
});
},
'build:unknown': function () {
// TODO: query the responsible runner to get the current output, etc.
},
test: function (project, branch) {
const user = this.user;
startJob(project, user, branch, 'TEST_ONLY');
},
deploy: function (project, branch) {
const user = this.user;
startJob(project, user, branch, 'TEST_AND_DEPLOY');
},
cancel: function (id) {
console.log('Got a request to cancel', id);
const self = this;
Job.findById(id)
.lean()
.exec(function (err, job) {
if (err || !job)
return console.error('[canceljob] error getting job', id, err);
Project.findOne({ name: job.project.toLowerCase() })
.lean()
.exec(function (err, project) {
if (err || !project)
return console.error('[canceljob] error getting project', id, err);
if (!job)
return console.error('[canceljob] Job not found', id);
if (User.projectAccessLevel(self.user, project) > 0) {
common.emitter.emit('job.cancel', id);
}
});
});
},
restart: function () {
console.log('Implementation needed');
},
},
};
function waiter(socket, event) {
var wait = {
event: event,
calls: [],
handler: function () {
wait.calls.push(arguments);
},
};
return wait;
}
function unWait(socket, waiter, handler) {
socket.removeListener(waiter.event, waiter.handler);
socket.on(waiter.event, handler);
for (let i = 0; i < waiter.calls.length; i++) {
handler.apply(null, waiter.calls[i]);
}
}
function kickoffJob(user, project, type, branch) {
const now = new Date();
let trigger;
let job;
branch = branch || 'master';
trigger = {
type: 'manual',
author: {
id: user._id,
email: user.email,
image: gravatar.url(user.email, {}, true),
name: user.name,
},
message: type === 'TEST_AND_DEPLOY'
? 'Manually Redeploying'
: 'Manually Retesting',
timestamp: now,
source: { type: 'UI', page: 'unknown' },
};
if (branch !== 'master') {
trigger.message += ` ${branch}`;
}
job = {
type: type,
user_id: user._id,
project: project,
ref: { branch: branch },
trigger: trigger,
created: now,
};
common.emitter.emit('job.prepare', job);
}
function startJob(projectName, user, branch, jobType) {
Project.findOne({ name: projectName })
.lean()
.exec(function (err, project) {
if (User.projectAccessLevel(user, project) > 0) {
kickoffJob(user, project.name, jobType, branch);
}
});
}
//# sourceMappingURL=user-socket.js.map