Files
Disco/Disco.Web/Areas/Config/Views/SystemConfig/Index.cshtml
T
2014-07-07 13:49:38 +10:00

595 lines
26 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 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" title="@Model.DiscoVersionBuilt.ToFullDateTime()">
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.ResponseTimestamp)</span>
</td>
</tr>
if (Model.UpdateLatestResponse.IsUpdatable(typeof(DiscoApplication).Assembly.GetName().Version))
{
<tr>
<th style="width: 135px">Update Available:
</th>
<td>
<div>
<i class="fa fa-info-circle fa-lg information"></i>&nbsp;Version @(Model.UpdateLatestResponse.Version) is available
</div>
<div class="smallMessage">
[Released @(CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.VersionReleasedTimestamp))]
</div>
<div class="smallMessage">@(new HtmlString(Model.UpdateLatestResponse.Blurb))</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">Forest:
</th>
<td>
@if (Model.ADForestServers == null)
{
<div>
@Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" }) @Html.LabelFor(m => m.ADSearchAllForestServers)
</div>
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>Forest servers are currently being retrieved.<br />
Try refreshing this page in a moment.
</p>
</div>
}
else
{
if (canConfigAD)
{
var canSearchEntireForest = (Model.ADForestServers.Count <= Disco.Services.Interop.ActiveDirectory.ActiveDirectory.MaxForestServerSearch);
<div>
@if (!canSearchEntireForest)
{
@Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" }) @Html.LabelFor(m => m.ADSearchAllForestServers)
<div class="info-box">
<p class="fa-p">
<i class="fa fa-exclamation-circle warning"></i>Disco will not search entire forests which consist of more than @(Disco.Services.Interop.ActiveDirectory.ActiveDirectory.MaxForestServerSearch) servers. Only servers within this site will be searched.
</p>
</div>
}
else
{
@Html.CheckBoxFor(m => m.ADSearchAllForestServers) @Html.LabelFor(m => m.ADSearchAllForestServers) @AjaxHelpers.AjaxLoader()
<div class="smallMessage">
If this setting is enabled, Disco will query all servers within the forest rather than only servers within this site.
</div>
<script>
$(function () {
document.DiscoFunctions.PropertyChangeHelper($('#ADSearchAllForestServers'), null, '@(Url.Action(MVC.API.System.UpdateActiveDirectorySearchAllForestServers()))', 'SearchAllForestServers');
});
</script>
}
</div>
}
else
{
<div>
@Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" }) @Html.LabelFor(m => m.ADSearchAllForestServers)
<div class="smallMessage">
If this setting is enabled, Disco will search all servers within the forest rather than only servers within this site.
</div>
</div>
}
<div>
<hr />
<span>All Servers:</span>
<ul id="Config_System_AD_ForestServers" class="none">
@{
var domainIndex = Model.ADDomains.ToDictionary(d => d.Name, StringComparer.OrdinalIgnoreCase);
foreach (var server in Model.ADForestServers.OrderBy(s => s))
{
var isSiteServer = Model.ADServers.Any(s => s.IsSiteServer && s.Name.Equals(server, StringComparison.OrdinalIgnoreCase));
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 (isSiteServer)
{ <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_ForestServers');
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">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 restrictions are in effect.</div>
<div class="smallMessage">When searching, the entire domain will be queried. This is suitable for most single-domain deployments.</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 Forest': 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();
$.getJSON(url, data, function (response, result) {
if (result != 'success' || response != 'OK') {
alert('Unable to change property "' + UpdatePropertyName + '":\n' + response);
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>
}
<div class="actionBar">
@Html.ActionLinkButton("Update Device Last Network Logons", MVC.API.System.UpdateLastNetworkLogonDates())
</div>