Files
Disco/Disco.Web/Areas/Config/Views/SystemConfig/Index.cshtml
T
2023-02-08 16:57:49 +11:00

899 lines
40 KiB
Plaintext

@model Disco.Web.Areas.Config.Models.SystemConfig.IndexModel
@{
Authorization.Require(Claims.Config.System.Show);
var canConfigProxy = Authorization.Has(Claims.Config.System.ConfigureProxy);
var canConfigEmail = Authorization.Has(Claims.Config.System.ConfigureEmail);
var canConfigAD = Authorization.Has(Claims.Config.System.ConfigureActiveDirectory);
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "System");
if (canConfigAD)
{
Html.BundleDeferred("~/Style/Fancytree");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-Fancytree");
Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers");
}
}
<div class="form" style="width: 450px">
<table>
<tr>
<th style="width: 135px">
Disco Version:
</th>
<td>
<div>
<code>@Model.DiscoVersion.ToString(4)</code>
</div>
<div class="smallMessage">
Built @CommonHelpers.FriendlyDate(Model.DiscoVersionBuilt, "Unknown")
</div>
</td>
</tr>
<tr>
<th style="width: 135px">
Database Connection:
</th>
<td>
<table class="sub">
<tr>
<th>Server:</th>
<td><span class="code">@Model.DatabaseServer</span></td>
</tr>
<tr>
<th>Database:</th>
<td><span class="code">@Model.DatabaseName</span></td>
</tr>
<tr>
<th>Authentication:</th>
<td>@Model.DatabaseAuthentication</td>
</tr>
@{if (Model.DatabaseSqlAuthUsername != null)
{
<tr>
<th>SQL&nbsp;User:</th>
<td><span class="code">@Model.DatabaseSqlAuthUsername</span></td>
</tr>
}
}
</table>
</td>
</tr>
<tr>
<th style="width: 135px">
Data Store Location:
</th>
<td>
<span class="code">@Model.DataStoreLocation</span>
</td>
</tr>
</table>
</div>
<div class="form" style="width: 450px; margin-top: 15px;">
<h2>Updates</h2>
<table>
@{
if (Model.UpdateLatestResponse == null)
{
<tr>
<th style="width: 135px">
Last Check:
</th>
<td>
<div class="error"><i class="fa fa-exclamation-circle fa-lg"></i>&nbsp;Never</div>
</td>
</tr>
}
else
{
<tr>
<th style="width: 135px">
Last Run:
</th>
<td>
<span>@CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.UpdateResponseDate.ToLocalTime())</span>
</td>
</tr>
if (Model.UpdateAvailable)
{
<tr>
<th style="width: 135px">
Update Available:
</th>
<td>
<div>
<i class="fa fa-info-circle fa-lg information"></i>&nbsp;Version @(Model.UpdateLatestResponse.LatestVersion) is available
</div>
<div class="smallMessage">
[Released @(CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.ReleasedDate))]
</div>
<div class="smallMessage">@(new HtmlString(Model.UpdateLatestResponse.Description))</div>
<a href="@(Model.UpdateLatestResponse.UrlLink)" target="_blank">Download Now</a>
</td>
</tr>
}
else
{
<tr>
<th style="width: 135px">
Status:
</th>
<td>
<i class="fa fa-check-square fa-lg success"></i>&nbsp;<span>The latest version is installed</span>
</td>
</tr>
}
}
}
<tr>
<th style="width: 135px">Check for Update:</th>
<td>
@{
if (Model.UpdateRunningStatus == null)
{
<span>@Html.ActionLinkSmallButton("Check Now", MVC.API.System.UpdateCheck())</span>
<span class="smallMessage">[Will run automatically <strong>@CommonHelpers.FriendlyDate(Model.UpdateNextScheduled, "Unknown")</strong>]</span>
}
else
{
<span>@Html.ActionLink("View Status", MVC.Config.Logging.TaskStatus(Model.UpdateRunningStatus.SessionId))</span>
<span class="smallMessage">[Running Now]</span>
}
}
@if (Model.UpdateBetaDeployment)
{
<hr />
<span class="alert"><i class="fa fa-info-circle fa-lg"></i>&nbsp;Beta Deployment</span>
}
</td>
</tr>
</table>
</div>
<div class="form" style="width: 450px; margin-top: 15px;">
<h2>Active Directory</h2>
<table>
<tr>
<th style="width: 135px">
Primary Domain:
</th>
<td>
<code><strong>@Model.ADPrimaryDomain.Name</strong> <span>[@Model.ADPrimaryDomain.NetBiosName]</span></code>
</td>
</tr>
<tr>
<th style="width: 135px">
Additional Domains:
</th>
<td>
@if (Model.ADDomains.Count > 1)
{
var adAdditionalDomains = Model.ADDomains.Where(d => d != Model.ADPrimaryDomain).OrderBy(d => d.Name).ToList();
var adDomainFirst = adAdditionalDomains.First();
<code>@adDomainFirst.Name <span>[@adDomainFirst.NetBiosName]</span></code>
foreach (var adDomain in adAdditionalDomains.Skip(1))
{
<hr />
<div>
<code>@adDomain.Name <span>[@adDomain.NetBiosName]</span></code>
</div>
}
}
else
{
<span class="smallMessage">&lt;None&gt;</span>
}
</td>
</tr>
<tr>
<th style="width: 135px">
Site:
</th>
<td>
<code><strong>@Model.ADSite.Name</strong></code>
</td>
</tr>
<tr>
<th style="width: 135px">
Servers:
</th>
<td>
<div>
@if (Model.ADServers.Count > 0)
{
<ul class="none">
@foreach (var server in Model.ADServers)
{
var serverDescription = string.Format("{0} [{1}]", server.Name.EndsWith(server.Domain.Name, StringComparison.OrdinalIgnoreCase) ? server.Name.Substring(0, server.Name.Length - server.Domain.Name.Length - 1) : server.Name, server.Domain.NetBiosName);
var reachable = server.IsAvailable;
<li>
@if (server.IsAvailable)
{
<i class="fa fa-check success fa-fw fa-lg" title="Available"></i>
}
else
{
<i class="fa fa-exclamation warning fa-fw fa-lg" title="Unavailable, will retry at @(server.AvailableWhen.Value.ToLongTimeString())"></i>
}
<code>@(serverDescription)</code>
@if (server.IsSiteServer)
{
<i class="fa fa-building-o information fa-fw" title="Site Server"></i>
}
else
{
<i class="fa fa-globe warning fa-fw" title="Not a Site Server"></i>
}
@if (server.IsWritable)
{
<i class="fa fa-pencil information fa-fw" title="Writable Domain Controller"></i>
}
</li>
}
</ul>
}
else
{
<div class="error">
<i class="fa fa-exclamation-circle fa-lg"></i>&nbsp;<span>None Found</span>
</div>
}
</div>
</td>
</tr>
<tr>
<th style="width: 135px">
Directory:
</th>
<td>
@if (Model.ADAllServers == null)
{
<div>
@Html.CheckBoxFor(m => m.ADSearchAllServers, new { disabled = "disabled" }) @Html.LabelFor(m => m.ADSearchAllServers)
</div>
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>Directory servers are currently being retrieved.<br />
Try refreshing this page in a moment.
</p>
</div>
}
else
{
if (canConfigAD)
{
var canSearchEntireDirectory = (Model.ADAllServers.Count <= Disco.Services.Interop.ActiveDirectory.ActiveDirectory.MaxAllServerSearch);
<div>
@if (!canSearchEntireDirectory)
{
@Html.CheckBoxFor(m => m.ADSearchAllServers, new { disabled = "disabled" }) @Html.LabelFor(m => m.ADSearchAllServers)
<div class="info-box">
<p class="fa-p">
<i class="fa fa-exclamation-circle warning"></i>Disco will not search the entire directory which consists of more than @(Disco.Services.Interop.ActiveDirectory.ActiveDirectory.MaxAllServerSearch) servers. Only servers within this site will be searched.
</p>
</div>
}
else
{
@Html.CheckBoxFor(m => m.ADSearchAllServers) @Html.LabelFor(m => m.ADSearchAllServers) @AjaxHelpers.AjaxLoader()
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>If this setting is enabled, Disco will query all servers within the directory rather than only servers within this site.
</p>
</div>
<script>
$(function () {
document.DiscoFunctions.PropertyChangeHelper($('#ADSearchAllServers'), null, '@(Url.Action(MVC.API.System.UpdateActiveDirectorySearchAllServers()))', 'SearchAllServers');
});
</script>
}
</div>
}
else
{
<div>
@Html.CheckBoxFor(m => m.ADSearchAllServers, new { disabled = "disabled" }) @Html.LabelFor(m => m.ADSearchAllServers)
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>If this setting is enabled, Disco will query all servers within the directory rather than only servers within this site.
</p>
</div>
</div>
}
<div>
<hr />
<span>All Servers:</span>
<ul id="Config_System_AD_AllServers" class="none">
@{
var domainIndex = Model.ADDomains.ToDictionary(d => d.Name, StringComparer.OrdinalIgnoreCase);
var siteServers = Model.ADServers.Where(s => s.IsSiteServer).ToDictionary(s => s.Name, StringComparer.OrdinalIgnoreCase);
foreach (var server in Model.ADAllServers.OrderBy(s => s))
{
var serverDescription = server;
if (server.Contains('.'))
{
Disco.Services.Interop.ActiveDirectory.ADDomain serverDomain;
if (domainIndex.TryGetValue(server.Substring(server.IndexOf('.') + 1), out serverDomain))
{
serverDescription = string.Format("{0} [{1}]", server.Substring(0, server.IndexOf('.')), serverDomain.NetBiosName);
}
}
<li>
<code>@serverDescription</code>@if (siteServers.ContainsKey(server))
{<i class="fa fa-building-o information fa-fw" title="Site Server"></i>}
</li>
}
}
</ul>
<script>
$(function () {
var toManyServers = 5;
var ul = $('#Config_System_AD_AllServers');
var ulLi = ul.find('li');
if (ulLi.length > toManyServers) {
var liMore = $('<li>').append(
$('<a>').attr('href', '#')
.text('Show All Servers (' + (ulLi.length - toManyServers) + ' more)')
.click(function () {
$(this).closest('li').remove();
ul.find('li').show();
return false;
}))
.insertAfter(ulLi[(toManyServers - 1)]);
ulLi.each(function (i) {
if (i > (toManyServers - 1))
$(this).hide();
});
}
});
</script>
</div>
}
</td>
</tr>
<tr>
<th style="width: 135px">
Searching:
</th>
<td>
@{
object ADSearchWildcardSuffixOnlyAttributes = null;
if (!canConfigAD)
{
ADSearchWildcardSuffixOnlyAttributes = new
{
disabled = "disabled"
};
}
}
@Html.CheckBoxFor(m => m.ADSearchWildcardSuffixOnly, ADSearchWildcardSuffixOnlyAttributes) @Html.LabelFor(m => m.ADSearchWildcardSuffixOnly) @AjaxHelpers.AjaxLoader()
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>If this setting is enabled, Disco will utilize Active Directory indexes to greatly improve search performance.
If disabled, more results may be returned however performance will be reduced especially in large Active Directory domains.
</p>
</div>
@if (canConfigAD)
{
<script>
$(function () {
document.DiscoFunctions.PropertyChangeHelper($('#ADSearchWildcardSuffixOnly'), null, '@(Url.Action(MVC.API.System.UpdateActiveDirectorySearchWildcardSuffixOnly()))', 'SearchWildcardSuffixOnly');
});
</script>
}
</td>
</tr>
<tr>
<th style="width: 135px">
Search Scope:
</th>
<td>
@if (Model.ADSearchContainers != null && Model.ADSearchContainers.Count > 0)
{
<div>Searching is restricted to the following Organisational&nbsp;Unit containers</div>
<ul id="Config_System_AD_SearchScope_DistinguishedNames">
@foreach (var adContainer in Model.ADSearchContainers)
{
<li data-distinguishedname="@adContainer.Item1"><code>@adContainer.Item3</code></li>
}
</ul>
}
else
{
<div>No Organisational&nbsp;Unit restrictions are in effect.</div>
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>When searching, the entire domain will be queried. This is suitable for most single-domain deployments.
</p>
</div>
}
@if (canConfigAD)
{
<div>
<hr />
<a id="Config_System_AD_SearchScope_Update" href="#" class="button small">Update</a>
</div>
<div id="Config_System_AD_SearchScope_Dialog" class="dialog" title="Search Scope">
<div id="Config_System_AD_SearchScope_Dialog_Loading">
@AjaxHelpers.AjaxLoader() Loading Organisational Units
</div>
<div id="Config_System_AD_SearchScope_Tree" class="organisationalUnitTree">
</div>
@using (Html.BeginForm(MVC.API.System.UpdateActiveDirectorySearchScope(null, redirect: true)))
{
}
</div>
<script>
$(function () {
var $dialog, $tree, tree, distinguishedNames;
function expandNodeTree(node) {
var parent = node.parent;
if (parent) {
expandNodeTree(parent);
if (!parent.isExpanded())
parent.setExpanded(true, { noAnimation: true, noEvents: false });
}
}
function selectDistinguishedNames() {
if (!distinguishedNames) {
distinguishedNames = $('#Config_System_AD_SearchScope_DistinguishedNames')
.find('li')
.map(function () { return $(this).attr('data-distinguishedname'); }).get();
}
if (tree) {
tree.visit(function (node) {
if ($.inArray(node.key, distinguishedNames) >= 0) {
node.setSelected(true);
expandNodeTree(node);
} else if (node.isSelected()) {
node.setSelected(false);
}
});
}
}
function update() {
if (!$dialog) {
$dialog = $('#Config_System_AD_SearchScope_Dialog').dialog({
autoOpen: false,
buttons: null,
draggable: false,
modal: true,
resizable: false,
width: 500,
height: 500
});
$loading = $('#Config_System_AD_SearchScope_Dialog_Loading');
$loading.find('i.ajaxLoading').show();
$tree = $('#Config_System_AD_SearchScope_Tree');
$dialog.css('overflow', 'visible');
$tree.css('height', '100%');
$.getJSON('@(Url.Action(MVC.API.System.DomainOrganisationalUnits()))', null, function (data) {
$loading.hide();
tree = $tree.fancytree({
source: data,
checkbox: true,
selectMode: 2,
keyboard: false,
fx: null
}).fancytree('getTree');
tree.$container.css('position', 'relative');
// Set Buttons
$dialog.dialog('option', 'buttons', {
'Search Entire Directory': function () {
var $this = $(this);
$this.css('overflow', 'hidden');
$this.dialog("disable");
$this.dialog("option", "buttons", null);
var $form = $dialog.find('form');
$form.submit();
},
'Save': function () {
var $this = $(this);
$this.css('overflow', 'hidden');
$this.dialog("disable");
$this.dialog("option", "buttons", null);
var nodes = tree.getSelectedNodes();
var $form = $dialog.find('form');
$.each(nodes, function (i, node) {
$('<input>').attr({ 'type': 'hidden', 'name': 'Containers', 'value': node.key }).appendTo($form);
});
$form.submit();
}
});
// Select & Expand
selectDistinguishedNames();
tree.options.fx = { height: "toggle", duration: 200 };
});
}
selectDistinguishedNames();
$dialog.dialog('open');
return false;
}
$('#Config_System_AD_SearchScope_Update').click(update);
});
</script>
}
</td>
</tr>
</table>
</div>
@if (canConfigProxy)
{
using (Html.BeginForm(MVC.API.System.UpdateProxySettings()))
{
<div class="form" style="width: 450px; margin-top: 15px;">
<h2>Proxy Settings</h2>
<table>
<tr>
<th style="width: 135px">
Address:
</th>
<td>
@Html.EditorFor(m => m.ProxyAddress)<br />
@Html.ValidationMessageFor(m => m.ProxyAddress)
</td>
</tr>
<tr>
<th style="width: 135px">
Port:
</th>
<td>
@Html.EditorFor(m => m.ProxyPort)<br />
@Html.ValidationMessageFor(m => m.ProxyPort)
</td>
</tr>
<tr>
<th style="width: 135px">
Username:
</th>
<td>
@Html.EditorFor(m => m.ProxyUsername)<br />
@Html.ValidationMessageFor(m => m.ProxyUsername)
</td>
</tr>
<tr>
<th style="width: 135px">
Password:
</th>
<td>
@Html.EditorFor(m => m.ProxyPassword)<br />
@Html.ValidationMessageFor(m => m.ProxyPassword)
</td>
</tr>
<tr>
<th style="width: 135px">
&nbsp;
</th>
<td>
<button id="Config_System_Proxy_Save" type="button" class="button small">Save Proxy Settings</button>@AjaxHelpers.AjaxLoader()
<script>
$(function () {
var button = $('#Config_System_Proxy_Save');
button.click(function () {
var url = '@(Url.Action(MVC.API.System.UpdateProxySettings()))';
var data = {
ProxyAddress: $('#ProxyAddress').val(),
ProxyPort: $('#ProxyPort').val(),
ProxyUsername: $('#ProxyUsername').val(),
ProxyPassword: $('#ProxyPassword').val()
}
var ajaxLoading = button.next('.ajaxLoading').first().show();
$.ajax({
type: 'POST',
dataType: 'json',
url: url,
data: data,
complete: function (response, result) {
if (result != 'success' || response.responseJSON != 'OK') {
alert('Unable to change proxy settings:\nCheck logs for more information');
ajaxLoading.hide();
} else {
ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
}
}
});
});
});
</script>
</td>
</tr>
</table>
</div>
}
}
else
{
<div class="form" style="width: 450px; margin-top: 15px;">
<h2>Proxy Settings</h2>
<table>
<tr>
<th style="width: 135px">
Address:
</th>
<td>
@Html.DisplayFor(m => m.ProxyAddress)
</td>
</tr>
<tr>
<th style="width: 135px">
Port:
</th>
<td>
@Html.DisplayFor(m => m.ProxyPort)
</td>
</tr>
<tr>
<th style="width: 135px">
Username:
</th>
<td>
@Html.DisplayFor(m => m.ProxyUsername)
</td>
</tr>
<tr>
<th style="width: 135px">
Password:
</th>
<td>
********
</td>
</tr>
</table>
</div>
}
@if (canConfigEmail)
{
<div class="form" style="width: 450px; margin-top: 15px;">
<h2>Email Settings</h2>
<table>
<tr>
<th style="width: 135px">
SMTP Server:
</th>
<td>
@Html.EditorFor(m => m.EmailSmtpServer)<br />
@Html.ValidationMessageFor(m => m.EmailSmtpServer)
</td>
</tr>
<tr>
<th style="width: 135px">
Port:
</th>
<td>
@Html.EditorFor(m => m.EmailSmtpPort)<br />
@Html.ValidationMessageFor(m => m.EmailSmtpPort)
</td>
</tr>
<tr>
<th style="width: 135px">
Default From Address:
</th>
<td>
@Html.EditorFor(m => m.EmailFromAddress)<br />
@Html.ValidationMessageFor(m => m.EmailFromAddress)
</td>
</tr>
<tr>
<th style="width: 135px">
Reply To Address:
</th>
<td>
@Html.EditorFor(m => m.EmailReplyToAddress)<br />
@Html.ValidationMessageFor(m => m.EmailReplyToAddress)
</td>
</tr>
<tr>
<th style="width: 135px">
&nbsp;
</th>
<td>
@Html.CheckBoxFor(m => m.EmailEnableSsl) @Html.LabelFor(m => m.EmailEnableSsl)
</td>
</tr>
<tr>
<th style="width: 135px">
Username:
</th>
<td>
@Html.EditorFor(m => m.EmailUsername)<br />
@Html.ValidationMessageFor(m => m.EmailUsername)
</td>
</tr>
<tr>
<th style="width: 135px">
Password:
</th>
<td>
@Html.EditorFor(m => m.EmailPassword)<br />
@Html.ValidationMessageFor(m => m.EmailPassword)
</td>
</tr>
<tr>
<th style="width: 135px">
&nbsp;
</th>
<td>
@Html.AntiForgeryToken()
<button id="Config_System_Email_Test" type="button" class="button small" @(Model.EmailIsConfigured ? null : "disabled")>Send Test Email</button>
<button id="Config_System_Email_Save" type="button" class="button small">Save Email Settings</button>@AjaxHelpers.AjaxLoader()
<div id="Config_System_Email_Test_Dialog" class="dialog" title="Send Test Email">
<h4><i class="fa fa-envelope information"></i>&nbsp;Recipient Email Address:</h4>
<br />
@using (Html.BeginForm(MVC.API.System.SendTestEmail(), FormMethod.Post))
{
<input type="hidden" name="redirect" value="true" />
<input id="Config_System_Email_Test_Recipient" name="Recipient" type="text" value="@CurrentUser.EmailAddress" />
@Html.AntiForgeryToken()
}
</div>
<script>
$(function () {
var button = $('#Config_System_Email_Save');
var testButton = $('#Config_System_Email_Test');
var testDialog = null;
button.click(function () {
var url = '@(Url.Action(MVC.API.System.UpdateEmailSettings()))';
var data = {
SmtpServer: $('#EmailSmtpServer').val(),
SmtpPort: $('#EmailSmtpPort').val(),
FromAddress: $('#EmailFromAddress').val(),
ReplyToAddress: $('#EmailReplyToAddress').val(),
EnableSsl: $('#EmailEnableSsl').is(':checked'),
Username: $('#EmailUsername').val(),
Password: $('#EmailPassword').val(),
'__RequestVerificationToken': button.parent().find('input[name="__RequestVerificationToken"]').first().val()
}
var ajaxLoading = button.next('.ajaxLoading').first().show();
$.ajax({
type: 'POST',
dataType: 'json',
url: url,
data: data,
complete: function (response, result) {
if (result != 'success' || response.responseJSON != 'OK') {
alert('Unable to change email settings:\nCheck logs for more information');
ajaxLoading.hide();
} else {
ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
if (!!$('#EmailSmtpServer').val()) {
testButton.removeAttr('disabled');
} else {
testButton.attr('disabled', 'disabled');
}
}
}
});
});
testButton.closest('table').find('td>input').change(function () {
testButton.attr('disabled', 'disabled');
});
testButton.click(function () {
if (!testDialog) {
testDialog = $('#Config_System_Email_Test_Dialog')
.dialog({
resizable: false,
height: 180,
modal: true,
autoOpen: false,
buttons: {
Send: function () {
var $this = $(this);
var recipientInput = $('#Config_System_Email_Test_Recipient');
if (!!recipientInput.val()) {
$this.dialog("disable");
$this.dialog("option", "buttons", null);
recipientInput.closest('form').submit()
} else {
alert('Enter the recipient address for the test email');
}
},
Cancel: function () {
$(this).dialog("close");
}
}
});
}
testDialog.dialog('open');
});
});
</script>
</td>
</tr>
</table>
</div>
}
else
{
<div class="form" style="width: 450px; margin-top: 15px;">
<h2>Email Settings</h2>
<table>
<tr>
<th style="width: 135px">
SMTP Server:
</th>
<td>
@Html.DisplayFor(m => m.EmailSmtpServer)
</td>
</tr>
<tr>
<th style="width: 135px">
Port:
</th>
<td>
@Html.DisplayFor(m => m.EmailSmtpPort)
</td>
</tr>
<tr>
<th style="width: 135px">
Default From Address:
</th>
<td>
@Html.DisplayFor(m => m.EmailFromAddress)
</td>
</tr>
<tr>
<th style="width: 135px">
Reply To Address:
</th>
<td>
@Html.DisplayFor(m => m.EmailReplyToAddress)
</td>
</tr>
<tr>
<th style="width: 135px">
Enable SSL:
</th>
<td>
@Html.CheckBoxFor(m => m.EmailEnableSsl, new { disabled = "disabled" }) @Html.LabelFor(m => m.EmailEnableSsl)
</td>
</tr>
<tr>
<th style="width: 135px">
Username:
</th>
<td>
@Html.DisplayFor(m => m.EmailUsername)
</td>
</tr>
<tr>
<th style="width: 135px">
Password:
</th>
<td>
********
</td>
</tr>
</table>
</div>
}
<div class="actionBar">
@Html.ActionLinkButton("Update Device Last Network Logons", MVC.API.System.UpdateLastNetworkLogonDates())
</div>