1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-18 01:03:14 +00:00

Updated user-sessions on MacOS to support getHomeFolder and getUsername

This commit is contained in:
Bryan Roe
2019-05-30 14:59:32 -07:00
parent e08d1996d5
commit 5b0a4899e2
3 changed files with 207 additions and 192 deletions

File diff suppressed because one or more lines are too long

View File

@@ -224,7 +224,7 @@ if (process.platform == 'darwin')
function macos_messageBox() function macos_messageBox()
{ {
this._ObjectID = 'message-box'; this._ObjectID = 'message-box';
this._initMessageServer = function _initMessageServer() this._initIPCBase = function _initIPCBase()
{ {
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; }); var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
@@ -232,263 +232,240 @@ function macos_messageBox()
{ {
ret.uid = require('user-sessions').consoleUid(); ret.uid = require('user-sessions').consoleUid();
} }
catch(e) catch (e)
{ {
ret._rej(e); ret._rej(e);
return (ret); return (ret);
} }
ret.ipcpath = '/var/tmp/' + process.execPath.split('/').pop() + '_ev'; ret.path = '/var/tmp/' + process.execPath.split('/').pop() + '_ev';
var n; var n;
try try
{ {
n = require('tls').generateRandomInteger('1', '99999'); n = require('tls').generateRandomInteger('1', '99999');
} }
catch(e) catch (e)
{ {
n = 0; n = 0;
} }
while (require('fs').existsSync(ret.ipcpath + n)) while (require('fs').existsSync(ret.path + n))
{ {
try try {
{
n = require('tls').generateRandomInteger('1', '99999'); n = require('tls').generateRandomInteger('1', '99999');
} }
catch (e) catch (e) {
{
++n; ++n;
} }
} }
ret.ipcpath = ret.ipcpath + n; ret.path = ret.path + n;
ret.tmpServiceName = 'meshNotificationServer' + n; ret.tmpServiceName = 'meshNotificationServer' + n;
require('service-manager').manager.installLaunchAgent(
{
name: tmpServiceName, servicePath: process.execPath, startType: 'AUTO_START',
sessionTypes: ['Aqua'], parameters: ['-exec', "require('message-box').startServer({path: '" + ret.ipcpath + ", service: '" + ret.tmpServiceName + "'}).on('close', function(){process.exit();});"]
});
require('service-manager').getLaunchAgent(ret.tmpServiceName).load(ret.uid);
return (ret); return (ret);
}; };
this.create = function create(title, caption, timeout) this.create = function create(title, caption, timeout)
{ {
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; }); // Start Local Server
ret.ipcpath = '/var/tmp/' + process.execPath.split('/').pop() + '_ev'; var ret = this._initIPCBase();
ret.title = title; ret.caption = caption; ret.timeout = timeout;
var n = 0; ret.server = this.startMessageServer(ret);
while (require('fs').existsSync(ret.ipcpath + n)) { ++n; } ret.server.ret = ret;
ret.ipcpath += n; ret.server.on('connection', function (c)
ret.title = title;
ret.caption = caption;
//ToDo: Install the message server
this.startServer({ path: ret.ipcpath });
// Create the Client
ret.client = require('net').createConnection({ path: ret.ipcpath }, function ()
{ {
var b = translateObject({ command: 'DIALOG', title: ret.title, caption: ret.caption, icon: 'caution', buttons: ['"Yes"', '"No"'], buttonDefault: 2, timeout: timeout }); this._connection = c;
this.write(b); c.promise = this.ret;
c.on('data', function (buffer)
{
if (buffer.len < 4 || buffer.readUInt32LE(0) > buffer.len) { this.unshift(buffer); }
var p = JSON.parse(buffer.slice(4, buffer.readUInt32LE(0)).toString());
switch (p.command)
{
case 'ERROR':
this.promise._rej(p.reason);
break;
case 'DIALOG':
if (p.timeout)
{
this.promise._rej('TIMEOUT');
}
else
{
this.promise._res(p.button);
}
break;
}
});
c.write(translateObject({ command: 'DIALOG', title: this.ret.title, caption: this.ret.caption, icon: 'caution', buttons: ['"Yes"', '"No"'], buttonDefault: 2, timeout: this.ret.timeout }));
}); });
ret.client.promise = ret;
ret.client.on('data', function (buffer) return (ret);
};
this.notify = function notify(title, caption)
{
// Start Local Server
var ret = this._initIPCBase();
ret.title = title; ret.caption = caption;
ret.server = this.startMessageServer(ret);
ret.server.ret = ret;
ret.server.on('connection', function (c)
{
this._connection = c;
c.promise = this.ret;
c.on('data', function (buffer)
{
if (buffer.len < 4 || buffer.readUInt32LE(0) > buffer.len) { this.unshift(buffer); }
var p = JSON.parse(buffer.slice(4, buffer.readUInt32LE(0)).toString());
switch (p.command)
{
case 'ERROR':
this.promise._rej(p.reason);
break;
case 'NOTIFY':
this.promise._res();
break;
}
});
c.write(translateObject({ command: 'NOTIFY', title: this.ret.title, caption: this.ret.caption }));
});
return (ret);
};
this.startClient = function startClient(options)
{
// Create the Client
console.log('Starting Client...');
options.osversion = require('service-manager').getOSVersion();
options.uid = require('user-sessions').consoleUid();
this.client = require('net').createConnection(options);
this.client._options = options;
this.client.on('data', function (buffer)
{ {
if (buffer.len < 4 || buffer.readUInt32LE(0) > buffer.len) { this.unshift(buffer); } if (buffer.len < 4 || buffer.readUInt32LE(0) > buffer.len) { this.unshift(buffer); }
var p = JSON.parse(buffer.slice(4, buffer.readUInt32LE(0)).toString()); var p = JSON.parse(buffer.slice(4, buffer.readUInt32LE(0)).toString());
switch (p.command) switch (p.command)
{ {
case 'ERROR': case 'NOTIFY':
this.promise._rej(p.reason); this._shell = require('child_process').execFile('/bin/sh', ['sh']);
break; this._shell.stdout.str = ''; this._shell.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
case 'DIALOG': this._shell.stderr.str = ''; this._shell.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
if (p.timeout) this._shell.stdin.write('osascript -e \'tell current application to display notification "' + p.caption + '" with title "' + p.title + '"\'\nexit\n');
this._shell.waitExit();
if (this._shell.stderr.str != '')
{ {
this.promise._rej('TIMEOUT'); this.end(translateObject({ command: 'ERROR', reason: this._shell.stderr.str }));
} }
else else
{ {
this.promise._res(p.button); this.end(translateObject({ command: 'NOTIFY', status: 0 }));
} }
break; break;
} case 'DIALOG':
}); var timeout = p.timeout ? (' giving up after ' + p.timeout) : '';
ret.client.on('end', function () var icon = p.icon ? ('with icon ' + p.icon) : '';
{ var buttons = p.buttons ? ('buttons {' + p.buttons.toString() + '}') : '';
this.promise._rej('Message Server abruptly disconnected'); if (p.buttonDefault != null)
}); {
ret.finally(function () { console.log('finally'); }); buttons += (' default button ' + p.buttonDefault)
return (ret); }
}; this._shell = require('child_process').execFile('/bin/sh', ['sh']);
this.notify = function notify(title, caption) this._shell.stdout.str = ''; this._shell.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
{ this._shell.stderr.str = ''; this._shell.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; }); this._shell.stdin.write('osascript -e \'tell current application to display dialog "' + p.caption + '" with title "' + p.title + '" ' + icon + ' ' + buttons + timeout + '\' | awk \'{ c=split($0, tokens, ","); split(tokens[1], val, ":"); if(c==1) { print val[2] } else { split(tokens[2], gu, ":"); if(gu[2]=="true") { print "_TIMEOUT_" } else { print val[2] } } }\'\nexit\n');
ret.ipcpath = '/var/tmp/' + process.execPath.split('/').pop() + '_ev'; this._shell.waitExit();
if (this._shell.stderr.str != '')
var n = 0; {
while (require('fs').existsSync(ret.ipcPath + n)) { ++n; } this.end(translateObject({ command: 'ERROR', reason: this._shell.stderr.str }));
ret.ipcpath += n; }
else
ret.title = title; {
ret.caption = caption; if (this._shell.stdout.str.trim() == '_TIMEOUT_')
//ToDo: Install the message server
this.startServer({ path: ret.ipcpath });
// Create the Client
ret.client = require('net').createConnection({ path: ret.ipcpath }, function ()
{
var b = translateObject({ command: 'NOTIFY', title: ret.title, caption: ret.caption });
this.write(b);
});
ret.client.promise = ret;
ret.client.on('data', function (buffer)
{
if (buffer.len < 4 || buffer.readUInt32LE(0) > buffer.len) { this.unshift(buffer); }
var p = JSON.parse(buffer.slice(4, buffer.readUInt32LE(0)).toString());
switch(p.command)
{
case 'ERROR':
this.promise._rej(p.reason);
break;
case 'NOTIFY':
this.promise._res();
break;
}
});
ret.client.on('end', function ()
{
this.promise._rej('Message Server abruptly disconnected');
});
return (ret);
};
this.startServer = function startServer(options)
{
if (require('fs').existsSync(options.path)) { require('fs').unlinkSync(options.path); }
this._messageServer = require('net').createServer();
this._messageServer.uid = require('user-sessions').consoleUid();
this._messageServer.osversion = require('service-manager').getOSVersion();
this._messageServer._options = options;
this._messageServer.timer = setTimeout(function (obj)
{
obj.close();
}, 5000, this._messageServer);
this._messageServer.listen(options);
this._messageServer.on('connection', function (c)
{
this._client = c;
this._client.timer = this.timer;
this._client.on('data', function (buffer)
{
if (buffer.length < 4) { this.unshift(buffer); }
if (buffer.length < buffer.readUInt32LE(0)) { this.unshift(buffer); }
var p = JSON.parse(buffer.slice(4, buffer.readUInt32LE(0)).toString().trim());
clearTimeout(this.timer);
switch (p.command)
{
case 'NOTIFY':
this._shell = require('child_process').execFile('/bin/sh', ['sh']);
this._shell.stdout.str = ''; this._shell.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
this._shell.stderr.str = ''; this._shell.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
this._shell.stdin.write('osascript -e \'tell current application to display notification "' + p.caption + '" with title "' + p.title + '"\'\nexit\n');
this._shell.waitExit();
if (this._shell.stderr.str != '')
{ {
this.end(translateObject({ command: 'ERROR', reason: this._shell.stderr.str })); this.end(translateObject({ command: 'DIALOG', timeout: true }));
} }
else else
{ {
this.end(translateObject({ command: 'NOTIFY', status: 0 })); this.end(translateObject({ command: 'DIALOG', button: this._shell.stdout.str.trim() }));
} }
break; }
case 'DIALOG': break;
var timeout = p.timeout ? (' giving up after ' + p.timeout) : ''; default:
var icon = p.icon ? ('with icon ' + p.icon) : ''; break;
var buttons = p.buttons ? ('buttons {' + p.buttons.toString() + '}') : ''; }
if (p.buttonDefault != null)
{
buttons += (' default button ' + p.buttonDefault)
}
this._shell = require('child_process').execFile('/bin/sh', ['sh']);
this._shell.stdout.str = ''; this._shell.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
this._shell.stderr.str = ''; this._shell.stderr.on('data', function (chunk) { this.str += chunk.toString(); });
this._shell.stdin.write('osascript -e \'tell current application to display dialog "' + p.caption + '" with title "' + p.title + '" ' + icon + ' ' + buttons + timeout + '\' | awk \'{ c=split($0, tokens, ","); split(tokens[1], val, ":"); if(c==1) { print val[2] } else { split(tokens[2], gu, ":"); if(gu[2]=="true") { print "_TIMEOUT_" } else { print val[2] } } }\'\nexit\n');
this._shell.waitExit();
if (this._shell.stderr.str != '')
{
this.end(translateObject({ command: 'ERROR', reason: this._shell.stderr.str }));
}
else
{
if (this._shell.stdout.str.trim() == '_TIMEOUT_')
{
this.end(translateObject({ command: 'DIALOG', timeout: true }));
}
else
{
this.end(translateObject({ command: 'DIALOG', button: this._shell.stdout.str.trim() }));
}
}
break;
default:
break;
}
});
}); });
this.client.on('error', function () { this.uninstall(); }).on('end', function () { this.uninstall(); });
this._messageServer.on('~', function () this.client.uninstall = function ()
{ {
//attachDebugger({ webport: 9998, wait: 1 }).then(console.log);
try
{
require('fs').unlinkSync(this._options.path);
}
catch (e)
{
}
// Need to uninstall ourselves // Need to uninstall ourselves
console.log('uninstall');
var s; var s;
try try
{ {
s = require('service-manager').manager.getLaunchAgent(this._options.service); s = require('service-manager').manager.getLaunchAgent(this._options.service);
} }
catch(ee) catch (ee)
{ {
console.log('LaunchAgent not found');
return; // Nothing to do if the service doesn't exist return; // Nothing to do if the service doesn't exist
} }
var child = require('child_process').execFile('/bin/sh', ['sh'], { detached: true }); var child = require('child_process').execFile('/bin/sh', ['sh'], { detached: true });
if (this.osversion.compareTo('10.10') < 0) if (this._options.osversion.compareTo('10.10') < 0)
{ {
// Just unload // Just unload
console.log('launchctl unload ' + s.plist + '\nrm ' + s.plist + '\nexit\n');
child.stdin.write('launchctl unload ' + s.plist + '\nrm ' + s.plist + '\nexit\n'); child.stdin.write('launchctl unload ' + s.plist + '\nrm ' + s.plist + '\nexit\n');
} }
else else
{ {
// Use bootout // Use bootout
child.stdin.write('launchctl bootout gui/' + this.uid + ' ' + s.plist + '\nrm ' + s.plist + '\nexit\n'); console.log('launchctl bootout gui/' + this._options.uid + ' ' + s.plist + '\nrm ' + s.plist + '\nexit\n');
child.stdin.write('launchctl bootout gui/' + this._options.uid + ' ' + s.plist + '\nrm ' + s.plist + '\nexit\n');
} }
try try
{ {
child.waitExit(); child.waitExit();
} }
catch(e) catch (e)
{ {
} }
};
return (this.client);
};
this.startMessageServer = function startMessageServer(options)
{
if (require('fs').existsSync(options.path)) { require('fs').unlinkSync(options.path); }
options.writableAll = true;
var ret = require('net').createServer();
ret.uid = require('user-sessions').consoleUid();
ret.osversion = require('service-manager').getOSVersion();
ret._options = options;
ret.timer = setTimeout(function (obj)
{
obj.close();
obj._options._rej('Connection timeout');
}, 5000, ret);
ret.listen(options);
ret.on('connection', function (c)
{
clearTimeout(this.timer);
});
ret.on('~', function ()
{
require('fs').unlinkSync(this._options.path);
}); });
return (this._messageServer); require('service-manager').manager.installLaunchAgent(
{
name: options.tmpServiceName, servicePath: process.execPath, startType: 'AUTO_START',
sessionTypes: ['Aqua'], parameters: ['-exec', "require('message-box').startClient({ path: '" + options.path + "', service: '" + options.tmpServiceName + "' }).on('end', function () { process.exit(); }).on('error', function () { process.exit(); });"]
});
require('service-manager').manager.getLaunchAgent(options.tmpServiceName).load(options.uid);
return (ret);
}; };
} }

View File

@@ -652,6 +652,38 @@ function UserSessions()
} }
else if(process.platform == 'darwin') else if(process.platform == 'darwin')
{ {
this.getUsername = function getUsername(uid)
{
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = '';
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
child.stdin.write("dscl . list /Users UniqueID | grep " + uid + " | awk '{ if($2==" + uid + "){ print $1 }}'\nexit\n");
child.waitExit();
if(child.stdout.str.trim() != '')
{
return (child.stdout.str.trim());
}
else
{
throw ('uid: ' + uid + ' not found');
}
};
this.getHomeFolder = function getHomeFolder(user)
{
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = '';
child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
child.stdin.write("dscl . -read /Users/" + user + " | grep NFSHomeDirectory | awk -F: '{ print $2 }'\nexit\n");
child.waitExit();
if (child.stdout.str.trim() != '')
{
return (child.stdout.str.trim());
}
else
{
throw ('user: ' + user + ' not found');
}
};
this._users = function () this._users = function ()
{ {
var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']); var child = require('child_process').execFile('/usr/bin/dscl', ['dscl', '.', 'list', '/Users', 'UniqueID']);