mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-22 21:31:35 +03:00
Bug fixes, added AmtWake to MeshCMD.
This commit is contained in:
parent
f4a8981d4f
commit
04dfeebe1e
Binary file not shown.
Binary file not shown.
@ -114,7 +114,7 @@ function run(argv) {
|
||||
//console.log('addedModules = ' + JSON.stringify(addedModules));
|
||||
var actionpath = 'meshaction.txt';
|
||||
if (args.actionfile != null) { actionpath = args.actionfile; }
|
||||
var actions = ['HELP', 'ROUTE', 'MICROLMS', 'AMTSCAN', 'AMTPOWER', 'AMTFEATURES', 'AMTNETWORK', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTINFODEBUG', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTACM', 'AMTDEACTIVATE', 'AMTACMDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG', 'AMTEVENTLOG', 'AMTPRESENCE', 'AMTWIFI'];
|
||||
var actions = ['HELP', 'ROUTE', 'MICROLMS', 'AMTSCAN', 'AMTPOWER', 'AMTFEATURES', 'AMTNETWORK', 'AMTLOADWEBAPP', 'AMTLOADSMALLWEBAPP', 'AMTLOADLARGEWEBAPP', 'AMTCLEARWEBAPP', 'AMTSTORAGESTATE', 'AMTINFO', 'AMTINFODEBUG', 'AMTVERSIONS', 'AMTHASHES', 'AMTSAVESTATE', 'AMTSCRIPT', 'AMTUUID', 'AMTCCM', 'AMTACM', 'AMTDEACTIVATE', 'AMTACMDEACTIVATE', 'SMBIOS', 'RAWSMBIOS', 'MESHCOMMANDER', 'AMTAUDITLOG', 'AMTEVENTLOG', 'AMTPRESENCE', 'AMTWIFI', 'AMTWAKE'];
|
||||
|
||||
// Load the action file
|
||||
var actionfile = null;
|
||||
@ -201,6 +201,7 @@ function run(argv) {
|
||||
console.log(' AmtNetwork - Intel AMT network interface settings.');
|
||||
console.log(' AmtScan - Search local network for Intel AMT devices.');
|
||||
console.log(' AmtWifi - Intel AMT Wifi interface settings.');
|
||||
console.log(' AmtWake - Intel AMT Wake Alarms.');
|
||||
console.log('\r\nHelp on a specific action using:\r\n');
|
||||
console.log(' meshcmd help [action]');
|
||||
exit(1); return;
|
||||
@ -395,7 +396,7 @@ function run(argv) {
|
||||
console.log('\r\nOptional arguments:\r\n');
|
||||
console.log(' --user [username] The Intel AMT login username, admin is default.');
|
||||
console.log(' --tls Specifies that TLS must be used.');
|
||||
console.log(' --list List of stored Wifi profile');
|
||||
console.log(' --list List Wifi profiles');
|
||||
console.log(' --add Add new Wifi profile');
|
||||
console.log(' --name New Wifi profile name');
|
||||
console.log(' --priority Priority of this profile - default 0');
|
||||
@ -404,6 +405,22 @@ function run(argv) {
|
||||
console.log(' --enc Wifi Encryption type (3 - TKIP, 4 - CCMP) - default 3');
|
||||
console.log(' --psk Wifi password/pre-shared key');
|
||||
console.log(' --del [profile-name] Delete new Wifi profile');
|
||||
} else if (action == 'amtwake') {
|
||||
console.log('AmtWake is used to view/set/remote Intel AMT Wake Alarms. Example usage:\r\n\r\n meshcmd amtwake --host 1.2.3.4 --user admin --pass mypassword --list');
|
||||
console.log('\r\nRequired arguments:\r\n');
|
||||
console.log(' --host [hostname] The IP address or DNS name of Intel AMT, 127.0.0.1 is default.');
|
||||
console.log(' --pass [password] The Intel AMT login password.');
|
||||
console.log(' --[action] Action options are list, add, del.');
|
||||
console.log('\r\nOptional arguments:\r\n');
|
||||
console.log(' --user [username] The Intel AMT login username, admin is default.');
|
||||
console.log(' --tls Specifies that TLS must be used.');
|
||||
console.log(' --list List wake alarms profile');
|
||||
console.log(' --add [alarm-name] Add new wake alarm');
|
||||
console.log(' --date [yyyy-mm-dd] Alarm date in year-month-day format');
|
||||
console.log(' --time (hh:mm:ss) Optional alarm time in hours:minutes:seconds format, default is 00:00:00.');
|
||||
console.log(' --interval (dd-hh-mm) Optional alarm interval in days-hours-minutes format, default is alarm once.');
|
||||
console.log(' --deletewhendone Indicates alarm is removed once triggered, default is to no remove.');
|
||||
console.log(' --del [alarm-name] Remove a wake alarm');
|
||||
} else {
|
||||
actions.shift();
|
||||
console.log('Invalid action, usage:\r\n\r\n meshcmd help [action]\r\n\r\nValid actions are: ' + actions.join(', ') + '.');
|
||||
@ -714,22 +731,24 @@ function run(argv) {
|
||||
if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
|
||||
if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; }
|
||||
if (args.add != null) {
|
||||
if ((args.name == null) || (typeof args.name != 'string') || args.name == '') {
|
||||
console.log("Wifi profile name is required."); exit(1); return;
|
||||
}
|
||||
if ((args.ssid == null) || (typeof args.ssid != 'string') || args.ssid == '') {
|
||||
console.log("Wifi SSID is required."); exit(1); return;
|
||||
}
|
||||
if ((args.psk == null) || (typeof args.psk != 'string') || args.psk == '') {
|
||||
console.log("Wifi password is required."); exit(1); return;
|
||||
}
|
||||
if ((args.name == null) || (typeof args.name != 'string') || args.name == '') { console.log("Wifi profile name is required."); exit(1); return; }
|
||||
if ((args.ssid == null) || (typeof args.ssid != 'string') || args.ssid == '') { console.log("Wifi SSID is required."); exit(1); return; }
|
||||
if ((args.psk == null) || (typeof args.psk != 'string') || args.psk == '') { console.log("Wifi password is required."); exit(1); return; }
|
||||
}
|
||||
if (args.del !=null) {
|
||||
if ((settings.name == null) || (typeof settings.name != 'string') || settings.name == '') {
|
||||
console.log("Wifi profile name is required."); exit(1); return;
|
||||
}
|
||||
if ((settings.name == null) || (typeof settings.name != 'string') || settings.name == '') { console.log("Wifi profile name is required."); exit(1); return; }
|
||||
}
|
||||
performAmtWifiConfig(args);
|
||||
} else if (settings.action == 'amtwake') { // Perform remote Intel AMT wake alarm operations
|
||||
if (settings.hostname == null) { settings.hostname = '127.0.0.1'; }
|
||||
if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
|
||||
if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; }
|
||||
if ((args.del != null) && ((typeof args.del != 'string') || args.del == '')) { console.log("Alarm name is required (--del [name])."); exit(1); return; }
|
||||
if (args.add != null) {
|
||||
if (((typeof args.add != 'string') || args.add == '')) { console.log("Wake alarm name is required (--add [name])."); exit(1); return; }
|
||||
if (((typeof args.date != 'string') || args.data == '')) { console.log("Wake alarm date is required (--date [yyyy-mm-dd])."); exit(1); return; }
|
||||
}
|
||||
performAmtWakeConfig(args);
|
||||
} else if (settings.action == 'amtfeatures') { // Perform remote Intel AMT feature configuration operation
|
||||
if (settings.hostname == null) { settings.hostname = '127.0.0.1'; }
|
||||
if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
|
||||
@ -2546,7 +2565,7 @@ function performAmtWifiConfig1(stack, name, response, status, args) {
|
||||
|
||||
if (args) {
|
||||
if (args.list) {
|
||||
console.log('List of AMT Wifi profiles:');
|
||||
console.log('List of Intel AMT Wifi profiles:');
|
||||
if (wifiProfiles.length==0) {
|
||||
console.log('No Wifi profiles is stored.');
|
||||
}
|
||||
@ -2611,6 +2630,119 @@ function performAmtWifiConfig1(stack, name, response, status, args) {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Intel AMT wake alarm configuration
|
||||
//
|
||||
|
||||
function _fmtdatetime(str) {
|
||||
return str.replace('T', ' ').replace('Z', '');
|
||||
}
|
||||
|
||||
function _fmtinterval(str) {
|
||||
var cl = str.replace('T', '').substring(str.indexOf('P') + 1);
|
||||
cl = ' ' + cl.replace('D', " days ").replace('H', " hours ").replace('M', " minutes ");
|
||||
cl = cl.replace(" 1 days ", " 1 day ").replace(" 1 hours ", " 1 hour ").replace(" 1 minutes ", " 1 minute ");
|
||||
return cl.substring(0, cl.length - 1);
|
||||
}
|
||||
|
||||
function _fmttimepad(str) {
|
||||
str = '' + str;
|
||||
while (str.length < 2) { str = '0' + str; }
|
||||
return str;
|
||||
}
|
||||
|
||||
function convertAmtDataStr(str) {
|
||||
var timeArray = str.split('Z').join('').split('T').join('-').split(':').join('-').split('-');
|
||||
return new Date(timeArray[0], timeArray[1] - 1, timeArray[2], timeArray[3], timeArray[4], timeArray[5]);
|
||||
}
|
||||
|
||||
function prepareAlarmOccurenceTemplate(id, nm, start, interval, del) {
|
||||
return '<d:AlarmTemplate xmlns:d=\"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_AlarmClockService\" xmlns:s=\"http://intel.com/wbem/wscim/1/ips-schema/1/IPS_AlarmClockOccurrence\"><s:InstanceID>' + id + '</s:InstanceID><s:StartTime><p:Datetime xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/common\">' + start + '</p:Datetime></s:StartTime><s:Interval><p:Interval xmlns:p=\"http://schemas.dmtf.org/wbem/wscim/1/common\">' + interval + '</p:Interval></s:Interval><s:DeleteOnCompletion>' + del + '</s:DeleteOnCompletion></d:AlarmTemplate>';
|
||||
}
|
||||
|
||||
function performAmtWakeConfig(args) {
|
||||
if ((settings.hostname == '127.0.0.1') || (settings.hostname.toLowerCase() == 'localhost')) {
|
||||
settings.noconsole = true; startLms(performAmtWakeConfig0, false, args);
|
||||
} else {
|
||||
performAmtWakeConfig0(1, args);
|
||||
}
|
||||
}
|
||||
|
||||
function performAmtWakeConfig0(state, args) {
|
||||
var transport = require('amt-wsman-duk');
|
||||
var wsman = require('amt-wsman');
|
||||
var amt = require('amt');
|
||||
wsstack = new wsman(transport, settings.hostname, settings.tls ? 16993 : 16992, settings.username, settings.password, settings.tls);
|
||||
amtstack = new amt(wsstack);
|
||||
amtstack.BatchEnum(null, ['IPS_AlarmClockOccurrence'], performAmtWakeConfig1, args);
|
||||
}
|
||||
|
||||
function performAmtWakeConfig1(stack, name, response, status, args) {
|
||||
if (status == 200) {
|
||||
var response = response['IPS_AlarmClockOccurrence'].responses;
|
||||
if (!args) { process.exit(0); return; }
|
||||
if (args.list) {
|
||||
if (response.length == 0) {
|
||||
console.log('No wake alarms.');
|
||||
} else {
|
||||
for (var i = 0; i < response.length; i++) {
|
||||
var waketime = convertAmtDataStr(response[i]['StartTime']['Datetime']);
|
||||
var t = waketime.toLocaleString(), tx = t.indexOf('.');
|
||||
if (tx >= 0) { t = t.substring(0, tx); }
|
||||
var details = response[i]['ElementName'] + ', wake on ' + t.replace(' ', ' at ');
|
||||
if (response[i]['Interval'] != null) { details += ' and each' + _fmtinterval(response[i]['Interval']['Interval']); }
|
||||
if (response[i]['DeleteOnCompletion'] == true) { details += ", delete when done"; }
|
||||
console.log(details);
|
||||
}
|
||||
}
|
||||
process.exit(0);
|
||||
} else if (args.del) {
|
||||
// Remove a wake alarm, start by looking to see if it exists
|
||||
var alarmFound = false;
|
||||
for (var i = 0; i < response.length; i++) { if (response[i]['ElementName'] == args.del) { alarmFound = true; } }
|
||||
if (alarmFound == false) { console.log("Wake alarm " + args.del + " could not be found."); process.exit(0); return; }
|
||||
// Remote the alarm
|
||||
stack.Delete('IPS_AlarmClockOccurrence', { InstanceID: args.del },
|
||||
function (stck, nm, resp, sts) {
|
||||
if (sts == 200) { console.log("Done."); } else { console.log("Failed to delete wake alarm " + args.del + "."); }
|
||||
process.exit(0);
|
||||
},
|
||||
0, 1);
|
||||
} else if (args.add) {
|
||||
// Add a wake alarm
|
||||
var alarmFound = false;
|
||||
for (var i = 0; i < response.length; i++) { if (response[i]['ElementName'] == args.add) { alarmFound = true; } }
|
||||
if (alarmFound) { console.log("Wake alarm " + args.add + " already exists."); process.exit(0); return; }
|
||||
if (typeof args.time != 'string') { args.time = '00:00:00'; }
|
||||
if (typeof args.interval != 'string') { args.interval = ''; }
|
||||
var alarm_name = args.add;
|
||||
var x1 = args.date.split('-');
|
||||
var x2 = args.time.split(':');
|
||||
var t = new Date(x1[0], x1[1] - 1, x1[2], x2[0], x2[1], 0, 0); // Not sure why, but month is 0 = JAN, 11 = DEC, seconds must be 00.
|
||||
var alarm_starttime = _fmttimepad(t.getFullYear()) + '-' + _fmttimepad(t.getMonth() + 1) + '-' + _fmttimepad(t.getDate()) + 'T' + _fmttimepad(t.getHours()) + ':' + _fmttimepad(t.getMinutes()) + ':' + _fmttimepad(t.getSeconds()) + 'Z';
|
||||
var x = args.interval.split('-');
|
||||
if (x.length != 3) { x = [0, 0, 0]; }
|
||||
var alarm_interval = 'P' + x[0] + 'DT' + x[1] + 'H' + x[2] + 'M';
|
||||
var alarm_doc = (args.deletewhendone != null);
|
||||
var tpl = prepareAlarmOccurenceTemplate(alarm_name, alarm_name, alarm_starttime, alarm_interval, alarm_doc);
|
||||
stack.wsman.ExecMethodXml(amtstack.CompleteName('AMT_AlarmClockService'), 'AddAlarm', tpl,
|
||||
function (ws, resuri, response, status) {
|
||||
if (status != 200) { console.log("Failed to add alarm. Status: " + status + ". Verify the alarm is for a future time."); }
|
||||
else if (response.Body['ReturnValue'] != 0) { console.log("Failed to add alarm " + response.Body['ReturnValueStr'] + ". Verify the alarm is for a future time."); }
|
||||
else { console.log("Done."); }
|
||||
process.exit(0);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
console.log("Unknown action, specify --list, --del or --add.");
|
||||
process.exit(0);
|
||||
}
|
||||
} else {
|
||||
console.log("Error, status " + status + ".");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Intel AMT feature configuration action
|
||||
//
|
||||
|
19
meshmail.js
19
meshmail.js
@ -300,14 +300,25 @@ module.exports.CreateMeshMail = function (parent) {
|
||||
parent.debug('email', 'SMTP response: ' + JSON.stringify(err) + ', ' + JSON.stringify(info));
|
||||
obj.sendingMail = false;
|
||||
if (err == null) {
|
||||
// Send the next mail
|
||||
obj.pendingMails.shift();
|
||||
obj.retry = 0;
|
||||
sendNextMail(); // Send the next mail
|
||||
sendNextMail();
|
||||
} else {
|
||||
obj.retry++;
|
||||
parent.debug('email', 'SMTP server failed: ' + JSON.stringify(err));
|
||||
console.log('SMTP server failed: ' + JSON.stringify(err));
|
||||
if (obj.retry < 6) { setTimeout(sendNextMail, 60000); } // Wait and try again
|
||||
parent.debug('email', 'SMTP server failed (Retry:' + obj.retry + '): ' + JSON.stringify(err));
|
||||
console.log('SMTP server failed (Retry:' + obj.retry + '/3): ' + JSON.stringify(err));
|
||||
// Wait and try again
|
||||
if (obj.retry < 3) {
|
||||
setTimeout(sendNextMail, 10000);
|
||||
} else {
|
||||
// Failed, send the next mail
|
||||
parent.debug('email', 'SMTP server failed (Skipping): ' + JSON.stringify(err));
|
||||
console.log('SMTP server failed (Skipping): ' + JSON.stringify(err));
|
||||
obj.pendingMails.shift();
|
||||
obj.retry = 0;
|
||||
sendNextMail();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
32
meshuser.js
32
meshuser.js
@ -812,6 +812,19 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'email': {
|
||||
if (parent.parent.mailserver == null) {
|
||||
r = "No email service enabled.";
|
||||
} else {
|
||||
if (cmdargs['_'].length != 3) {
|
||||
r = "Usage: email \"user@sample.com\" \"Subject\" \"Message\".";
|
||||
} else {
|
||||
parent.parent.mailserver.sendMail(cmdargs['_'][0], cmdargs['_'][1], cmdargs['_'][2]);
|
||||
r = "Done.";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'le': {
|
||||
if (parent.parent.letsencrypt == null) {
|
||||
r = "Let's Encrypt not in use.";
|
||||
@ -3871,6 +3884,25 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'emailuser': { // Send a email message to a user
|
||||
var errMsg = null, emailuser = null;
|
||||
if (parent.parent.mailserver == null) { errMsg = 'Email server not enabled'; }
|
||||
else if ((user.siteadmin & 2) == 0) { errMsg = 'No user management rights'; }
|
||||
else if (common.validateString(command.userid, 1, 2048) == false) { errMsg = 'Invalid userid'; }
|
||||
else if (common.validateString(command.subject, 1, 1000) == false) { errMsg = 'Invalid subject message'; }
|
||||
else if (common.validateString(command.msg, 1, 10000) == false) { errMsg = 'Invalid message'; }
|
||||
else {
|
||||
emailuser = parent.users[command.userid];
|
||||
if (emailuser == null) { errMsg = 'Invalid userid'; }
|
||||
else if (emailuser.email == null) { errMsg = 'No validated email address for this user'; }
|
||||
else if (emailuser.emailVerified !== true) { errMsg = 'No validated email address for this user'; }
|
||||
}
|
||||
|
||||
if (errMsg != null) { displayNotificationMessage(errMsg); break; }
|
||||
parent.parent.mailserver.sendMail(emailuser.email, command.subject, command.msg);
|
||||
displayNotificationMessage("Email sent.");
|
||||
break;
|
||||
}
|
||||
case 'getClip': {
|
||||
if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.5.31",
|
||||
"version": "0.5.32",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
2
public/scripts/amt-wsman-0.2.0-min.js
vendored
2
public/scripts/amt-wsman-0.2.0-min.js
vendored
File diff suppressed because one or more lines are too long
@ -2332,6 +2332,10 @@ a {
|
||||
background-color: gray;
|
||||
}
|
||||
|
||||
.night #deskToolsAreaTop {
|
||||
background-color: #222;
|
||||
}
|
||||
|
||||
#deskToolsArea {
|
||||
position: absolute;
|
||||
top: 26px;
|
||||
@ -2342,6 +2346,10 @@ a {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.night #deskToolsArea {
|
||||
background-color: #222;
|
||||
}
|
||||
|
||||
#deskToolsHeader {
|
||||
border-bottom: 1px solid darkgray;
|
||||
padding: 3px;
|
||||
@ -2390,6 +2398,14 @@ a {
|
||||
background-color: #EFE8B6;
|
||||
}
|
||||
|
||||
.night .deskToolsBar {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.night .deskToolsBar:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
#deskarea4 {
|
||||
grid-area: deskarea4;
|
||||
-ms-grid-column: 1;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4982,6 +4982,7 @@
|
||||
if (node == null) return;
|
||||
var mesh = meshes[node.meshid];
|
||||
var meshrights = GetNodeRights(node);
|
||||
var deviceSwitch = ((currentNode == null) || (currentNode._id != nodeid));
|
||||
if (!currentNode || currentNode._id != node._id || refresh == true) {
|
||||
currentNode = node;
|
||||
|
||||
@ -5269,9 +5270,11 @@
|
||||
}
|
||||
|
||||
// Clear user consent status if present
|
||||
if (deviceSwitch) {
|
||||
p11clearConsoleMsg();
|
||||
p12clearConsoleMsg();
|
||||
p13clearConsoleMsg();
|
||||
}
|
||||
|
||||
// Device refresh plugin handler
|
||||
if (pluginHandler != null) {
|
||||
@ -10159,6 +10162,18 @@
|
||||
function showSendSMSValidate() { QE('idx_dlgOkButton', Q('d2smsText').value.length > 0); }
|
||||
function showSendSMSEx(b, tag) { if (Q('d2smsText').value.length > 0) { meshserver.send({ action: 'smsuser', userid: decodeURIComponent(tag), msg: Q('d2smsText').value }); } }
|
||||
|
||||
function showSendEmail(userid) {
|
||||
if (xxdialogMode) return;
|
||||
var x = '<input id=d2emailSubject style=background-color:#fcf3cf;width:100% placeholder="' + "Subject" + '"></input>';
|
||||
x += '<textarea id=d2emailText maxlength=10000 style="background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:auto" onKeyUp=showSendEmailValidate()></textarea>';
|
||||
setDialogMode(2, "Send Email", 3, showSendEmailEx, x, userid);
|
||||
Q('d2emailSubject').focus();
|
||||
showSendEmailValidate();
|
||||
}
|
||||
|
||||
function showSendEmailValidate() { QE('idx_dlgOkButton', (Q('d2emailSubject').value.length > 0) && (Q('d2emailText').value.length > 0)); }
|
||||
function showSendEmailEx(b, tag) { if (Q('d2emailText').value.length > 0) { meshserver.send({ action: 'emailuser', userid: decodeURIComponent(tag), subject: Q('d2emailSubject').value, msg: Q('d2emailText').value }); } }
|
||||
|
||||
function showUserAlertDialog(e, userid) {
|
||||
if (xxdialogMode) return;
|
||||
haltEvent(e);
|
||||
@ -10916,6 +10931,7 @@
|
||||
// Add action buttons
|
||||
x += '<input type=button value="' + "Notes" + '" title="' + "View notes about this user" + '" onclick=showNotes(false,"' + userid + '") />';
|
||||
if (user.phone && (features & 0x02000000)) { x += '<input type=button value="' + "SMS" + '" title="' + "Send a SMS message to this user" + '" onclick=showSendSMS("' + userid + '") />'; }
|
||||
if ((typeof user.email == 'string') && (user.emailVerified === true) && (features & 0x00000040)) { x += '<input type=button value="' + "Email" + '" title="' + "Send a email message to this user" + '" onclick=showSendEmail("' + userid + '") />'; }
|
||||
if (!self && (activeSessions > 0)) { x += '<input type=button value="' + "Notify" + '" title="' + "Send user notification" + '" onclick=showUserAlertDialog(event,"' + userid + '") />'; }
|
||||
|
||||
// Setup the panel
|
||||
|
Loading…
Reference in New Issue
Block a user