feature: pending device enrollment approval
This commit is contained in:
@@ -41,6 +41,9 @@ namespace Disco.Client.Extensions
|
||||
if (!string.IsNullOrEmpty(enrolResponse.ErrorMessage))
|
||||
throw new ClientServiceException("Enrolment", enrolResponse.ErrorMessage);
|
||||
|
||||
if (enrolResponse.IsPending)
|
||||
return;
|
||||
|
||||
// Offline Domain Join
|
||||
bool requireReboot = enrolResponse.ApplyOfflineDomainJoin();
|
||||
|
||||
|
||||
+30
-7
@@ -122,17 +122,40 @@ namespace Disco.Client
|
||||
EnrolResponse response = null;
|
||||
|
||||
// Build Request
|
||||
Presentation.UpdateStatus("Enrolling Device", "Building enrolment request and preparing to send data to the server.", true, -1);
|
||||
Presentation.UpdateStatus("Enrolling Device", "Building enrollment request and preparing to send data to the server.", true, -1);
|
||||
request = new Enrol();
|
||||
request.Build();
|
||||
|
||||
// Send Request
|
||||
Presentation.UpdateStatus("Enrolling Device", "Sending the enrolment request to the server.", true, -1);
|
||||
response = request.Post(Program.IsAuthenticated);
|
||||
var startTime = DateTimeOffset.Now;
|
||||
do
|
||||
{
|
||||
// Send Request
|
||||
Presentation.UpdateStatus("Enrolling Device", "Sending the enrollment request to the server.", true, -1);
|
||||
response = request.Post(Program.IsAuthenticated);
|
||||
|
||||
// Process Response
|
||||
Presentation.UpdateStatus("Enrolling Device", "Processing the enrolment response from the server.", true, -1);
|
||||
response.Process();
|
||||
// Process Response
|
||||
Presentation.UpdateStatus("Enrolling Device", "Processing the enrollment response from the server.", true, -1);
|
||||
response.Process();
|
||||
|
||||
if (response.IsPending)
|
||||
{
|
||||
request.PendingSessionId = response.SessionId;
|
||||
request.PendingAuthorization = response.PendingAuthorization;
|
||||
|
||||
// Session Pending
|
||||
var totalSeconds = (response.PendingTimeout - startTime).TotalSeconds;
|
||||
var secondsConsumed = (DateTimeOffset.Now - startTime).TotalSeconds;
|
||||
var progress = (int)((secondsConsumed / totalSeconds) * 100);
|
||||
|
||||
Presentation.UpdateStatus("Pending Device Enrollment Approval", $"Waiting for enrollment session to be approved.{Environment.NewLine}Reason: {response.PendingReason}", true, progress);
|
||||
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Session Complete
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
// Complete
|
||||
return true;
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Disco.ClientBootstrapper
|
||||
this.progressBar.Visible = true;
|
||||
if (Progress.HasValue)
|
||||
{
|
||||
if (Progress.Value > 0)
|
||||
if (Progress.Value >= 0)
|
||||
{
|
||||
this.progressBar.Value = Math.Min(Progress.Value, 100);
|
||||
this.progressBar.Style = ProgressBarStyle.Continuous;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Disco.Data.Repository;
|
||||
using System;
|
||||
|
||||
namespace Disco.Data.Configuration.Modules
|
||||
{
|
||||
@@ -6,33 +7,24 @@ namespace Disco.Data.Configuration.Modules
|
||||
{
|
||||
public BootstrapperConfiguration(DiscoDataContext Database) : base(Database) { }
|
||||
|
||||
public override string Scope
|
||||
{
|
||||
get { return "Bootstrapper"; }
|
||||
}
|
||||
public override string Scope { get; } = "Bootstrapper";
|
||||
|
||||
public string MacSshUsername
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Get("root");
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Set(value);
|
||||
}
|
||||
get => Get("root");
|
||||
set => Set(value);
|
||||
}
|
||||
|
||||
public string MacSshPassword
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetDeobsfucated(string.Empty);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetObsfucated(value);
|
||||
}
|
||||
get => GetDeobsfucated(string.Empty);
|
||||
set => SetObsfucated(value);
|
||||
}
|
||||
|
||||
public TimeSpan PendingTimeout
|
||||
{
|
||||
get => TimeSpan.FromSeconds(Get(30 * 60)); // 30 minutes default
|
||||
set => Set((int)value.TotalSeconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,5 +25,8 @@ namespace Disco.Models.ClientServices
|
||||
public List<Certificate> Certificates { get; set; }
|
||||
|
||||
public List<WirelessProfile> WirelessProfiles { get; set; }
|
||||
|
||||
public string PendingSessionId { get; set; }
|
||||
public string PendingAuthorization { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Disco.Models.ClientServices.EnrolmentInformation;
|
||||
using System;
|
||||
|
||||
namespace Disco.Models.ClientServices
|
||||
{
|
||||
@@ -26,5 +27,10 @@ namespace Disco.Models.ClientServices
|
||||
public bool RequireReboot { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public bool IsPending { get; set; }
|
||||
public string PendingAuthorization { get; set; }
|
||||
public string PendingReason { get; set; }
|
||||
public DateTimeOffset PendingTimeout { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Models.UI.Config.Enrolment
|
||||
namespace Disco.Models.UI.Config.Enrolment
|
||||
{
|
||||
public interface ConfigEnrolmentIndexModel : BaseUIModel
|
||||
{
|
||||
string MacSshUsername { get; set; }
|
||||
int PendingTimeoutMinutes { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Disco.Models.Services.Jobs.JobLists;
|
||||
using Disco.Models.ClientServices;
|
||||
using Disco.Models.Services.Jobs.JobLists;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Disco.Models.UI.Job
|
||||
{
|
||||
@@ -6,5 +8,6 @@ namespace Disco.Models.UI.Job
|
||||
{
|
||||
JobTableModel MyJobs { get; set; }
|
||||
JobTableModel StaleJobs { get; set; }
|
||||
List<EnrolResponse> PendingEnrollments { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ namespace Disco.Services.Devices.Enrolment
|
||||
SessionProgress,
|
||||
SessionDevice,
|
||||
SessionDeviceInfo,
|
||||
SessionPending,
|
||||
SessionPendingApproved,
|
||||
SessionPendingRejected,
|
||||
SessionContinuing,
|
||||
SessionFinished = 20,
|
||||
SessionDiagnosticInformation,
|
||||
SessionWarning,
|
||||
@@ -43,7 +47,7 @@ namespace Disco.Services.Devices.Enrolment
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Device Enrolment";
|
||||
return "Device Enrollment";
|
||||
}
|
||||
}
|
||||
public override int ModuleId
|
||||
@@ -77,6 +81,43 @@ namespace Disco.Services.Devices.Enrolment
|
||||
System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType)
|
||||
});
|
||||
}
|
||||
public static void LogSessionPending(string SessionId, string HostId, EnrolmentTypes EnrolmentType, string Reason)
|
||||
{
|
||||
Log(EventTypeIds.SessionPending, new object[]
|
||||
{
|
||||
SessionId,
|
||||
HostId,
|
||||
System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType),
|
||||
Reason
|
||||
});
|
||||
}
|
||||
public static void LogSessionPendingApproved(string SessionId, string Username, string Reason)
|
||||
{
|
||||
Log(EventTypeIds.SessionPendingApproved, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Username,
|
||||
Reason
|
||||
});
|
||||
}
|
||||
public static void LogSessionPendingRejected(string SessionId, string Username, string Reason)
|
||||
{
|
||||
Log(EventTypeIds.SessionPendingRejected, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Username,
|
||||
Reason
|
||||
});
|
||||
}
|
||||
public static void LogSessionContinuing(string SessionId, string HostId, EnrolmentTypes EnrolmentType)
|
||||
{
|
||||
Log(EventTypeIds.SessionContinuing, new object[]
|
||||
{
|
||||
SessionId,
|
||||
HostId,
|
||||
System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType)
|
||||
});
|
||||
}
|
||||
public static void LogSessionDevice(string SessionId, string DeviceSerialNumber, int? DeviceModelId)
|
||||
{
|
||||
Log(EventTypeIds.SessionDevice, new object[]
|
||||
@@ -298,7 +339,7 @@ namespace Disco.Services.Devices.Enrolment
|
||||
Id = (int)EventTypeIds.SessionStarting,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Session Starting",
|
||||
Format = "Starting '{2}' Enrolment for {1} (Session# {0})",
|
||||
Format = "Starting '{2}' Enrollment for {1} (Session# {0})",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
@@ -338,6 +379,50 @@ namespace Disco.Services.Devices.Enrolment
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.SessionPending,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Session Pending",
|
||||
Format = "Pending '{2}' Enrollment for {1} (Session# {0}; Reason: {3})",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.SessionPendingApproved,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Session Pending Approved",
|
||||
Format = "Pending enrollment approved by {1} (Session# {0}; Reason: {2})",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.SessionPendingRejected,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Session Pending Rejected",
|
||||
Format = "Pending enrollment rejected by {1} (Session# {0}; Reason: {2})",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.SessionContinuing,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Session Continuing",
|
||||
Format = "Continuing '{2}' Enrollment for {1} (Session# {0})",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.SessionFinished,
|
||||
ModuleId = _ModuleId,
|
||||
|
||||
@@ -5,15 +5,64 @@ using Disco.Services.Authorization;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Disco.Services.Devices.Enrolment
|
||||
{
|
||||
public static class WindowsDeviceEnrolment
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, EnrolResponse> pendingEnrolments = new ConcurrentDictionary<string, EnrolResponse>();
|
||||
|
||||
private static void CleanupPendingEnrolments()
|
||||
{
|
||||
var now = DateTimeOffset.Now;
|
||||
var expiredEnrolments = pendingEnrolments
|
||||
.Where(e => e.Value.PendingTimeout < now)
|
||||
.Select(kvp => kvp.Key).ToList();
|
||||
foreach (var expiredEnrolment in expiredEnrolments)
|
||||
pendingEnrolments.TryRemove(expiredEnrolment, out _);
|
||||
}
|
||||
|
||||
public static List<EnrolResponse> GetPendingEnrolments()
|
||||
{
|
||||
var now = DateTimeOffset.Now;
|
||||
return pendingEnrolments.Values
|
||||
.Where(e => e.PendingTimeout > now && e.IsPending)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static void ResolvePendingEnrollment(string sessionId, bool approve, string username, string reason)
|
||||
{
|
||||
if (!pendingEnrolments.TryGetValue(sessionId, out var enrolResponse))
|
||||
throw new InvalidOperationException("The pending session is invalid or has expired");
|
||||
if (enrolResponse.PendingTimeout < DateTimeOffset.Now)
|
||||
{
|
||||
pendingEnrolments.TryRemove(sessionId, out _);
|
||||
throw new InvalidOperationException("The pending session has expired");
|
||||
}
|
||||
if (!enrolResponse.IsPending)
|
||||
return;
|
||||
|
||||
enrolResponse.IsPending = false;
|
||||
if (approve)
|
||||
{
|
||||
enrolResponse.ErrorMessage = null;
|
||||
EnrolmentLog.LogSessionPendingApproved(sessionId, username, reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
enrolResponse.ErrorMessage = $"Enrollment rejected";
|
||||
EnrolmentLog.LogSessionPendingRejected(sessionId, username, reason);
|
||||
}
|
||||
}
|
||||
|
||||
public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Enrol Request)
|
||||
{
|
||||
CleanupPendingEnrolments();
|
||||
|
||||
ADMachineAccount adMachineAccount = null;
|
||||
|
||||
EnrolResponse response = new EnrolResponse();
|
||||
@@ -29,14 +78,49 @@ namespace Disco.Services.Devices.Enrolment
|
||||
return domain.GetAvailableDomainController(RequireWritable: true);
|
||||
});
|
||||
|
||||
string sessionId = Guid.NewGuid().ToString("B");
|
||||
response.SessionId = sessionId;
|
||||
|
||||
EnrolmentLog.LogSessionStarting(sessionId, Request.SerialNumber, EnrolmentTypes.Normal);
|
||||
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
||||
|
||||
try
|
||||
{
|
||||
string sessionId;
|
||||
bool sessionApproved = false;
|
||||
if (!string.IsNullOrWhiteSpace(Request.PendingSessionId))
|
||||
{
|
||||
if (!pendingEnrolments.TryGetValue(Request.PendingSessionId, out var pendingResponse))
|
||||
throw new EnrolmentSafeException("The pending session is invalid or has expired");
|
||||
if (pendingResponse.PendingTimeout < DateTimeOffset.Now)
|
||||
{
|
||||
pendingEnrolments.TryRemove(Request.PendingSessionId, out _);
|
||||
throw new EnrolmentSafeException("The pending session has expired");
|
||||
}
|
||||
if (!string.Equals(pendingResponse.PendingAuthorization, Request.PendingAuthorization, StringComparison.Ordinal))
|
||||
throw new EnrolmentSafeException("The pending session authorization is incorrect");
|
||||
|
||||
sessionId = pendingResponse.SessionId;
|
||||
response = pendingResponse;
|
||||
|
||||
// still pending?
|
||||
if (response.IsPending)
|
||||
return response;
|
||||
|
||||
// session rejected?
|
||||
if (!string.IsNullOrWhiteSpace(response.ErrorMessage))
|
||||
throw new EnrolmentSafeException(response.ErrorMessage);
|
||||
|
||||
// session approved; continue
|
||||
sessionApproved = true;
|
||||
|
||||
EnrolmentLog.LogSessionContinuing(sessionId, Request.SerialNumber, EnrolmentTypes.Normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
sessionId = Guid.NewGuid().ToString("B");
|
||||
response.SessionId = sessionId;
|
||||
|
||||
EnrolmentLog.LogSessionStarting(sessionId, Request.SerialNumber, EnrolmentTypes.Normal);
|
||||
}
|
||||
|
||||
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
||||
|
||||
if (Request.SerialNumber.Contains("/") || Request.SerialNumber.Contains(@"\"))
|
||||
throw new EnrolmentSafeException(@"The serial number cannot contain '/' or '\' characters.");
|
||||
|
||||
@@ -50,46 +134,71 @@ namespace Disco.Services.Devices.Enrolment
|
||||
|
||||
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.SerialNumber).FirstOrDefault();
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco ICT Permissions");
|
||||
if (isAuthenticated)
|
||||
if (!sessionApproved)
|
||||
{
|
||||
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
|
||||
try
|
||||
{
|
||||
if (!authenticatedToken.Has(Claims.ComputerAccount))
|
||||
throw new EnrolmentSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.SerialNumber, authenticatedToken.User.UserId));
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DNSDomainName);
|
||||
|
||||
if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.ComputerName), StringComparison.OrdinalIgnoreCase))
|
||||
throw new EnrolmentSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.SerialNumber, authenticatedToken.User.UserId));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RepoDevice == null)
|
||||
{
|
||||
throw new EnrolmentSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.SerialNumber));
|
||||
}
|
||||
if (!RepoDevice.AllowUnauthenticatedEnrol)
|
||||
{
|
||||
if (RepoDevice.DeviceProfile.AllowUntrustedReimageJobEnrolment)
|
||||
if (isAuthenticated)
|
||||
{
|
||||
if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0)
|
||||
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
|
||||
{
|
||||
throw new EnrolmentSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.SerialNumber));
|
||||
if (!authenticatedToken.Has(Claims.ComputerAccount))
|
||||
throw new EnrolmentSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.SerialNumber, authenticatedToken.User.UserId));
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DNSDomainName);
|
||||
|
||||
if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.ComputerName), StringComparison.OrdinalIgnoreCase))
|
||||
throw new EnrolmentSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.SerialNumber, authenticatedToken.User.UserId));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EnrolmentSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.SerialNumber));
|
||||
if (RepoDevice == null)
|
||||
{
|
||||
throw new EnrolmentSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.SerialNumber));
|
||||
}
|
||||
if (!RepoDevice.AllowUnauthenticatedEnrol)
|
||||
{
|
||||
if (RepoDevice.DeviceProfile.AllowUntrustedReimageJobEnrolment)
|
||||
{
|
||||
if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0)
|
||||
{
|
||||
throw new EnrolmentSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.SerialNumber));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EnrolmentSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.SerialNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (EnrolmentSafeException ex)
|
||||
{
|
||||
response.IsPending = true;
|
||||
response.PendingReason = ex.Message;
|
||||
using (var rng = new RNGCryptoServiceProvider())
|
||||
{
|
||||
var authBytes = new byte[33]; // 264 bits (base64-aligned)
|
||||
rng.GetBytes(authBytes);
|
||||
response.PendingAuthorization = Convert.ToBase64String(authBytes);
|
||||
}
|
||||
response.PendingTimeout = DateTimeOffset.Now.Add(Database.DiscoConfiguration.Bootstrapper.PendingTimeout);
|
||||
|
||||
EnrolmentLog.LogSessionPending(sessionId, Request.SerialNumber, EnrolmentTypes.Normal, response.PendingReason);
|
||||
|
||||
if (pendingEnrolments.TryAdd(sessionId, response))
|
||||
return response;
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (Request.IsPartOfDomain && !string.IsNullOrWhiteSpace(Request.ComputerName))
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 20, "Loading Active Directory Computer Account");
|
||||
System.Guid? uuidGuid = null;
|
||||
System.Guid? macAddressGuid = null;
|
||||
Guid? uuidGuid = null;
|
||||
Guid? macAddressGuid = null;
|
||||
if (!string.IsNullOrEmpty(Request.Hardware.UUID))
|
||||
uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.Hardware.UUID);
|
||||
|
||||
@@ -382,24 +491,26 @@ namespace Disco.Services.Devices.Enrolment
|
||||
}
|
||||
catch (EnrolmentSafeException ex)
|
||||
{
|
||||
EnrolmentLog.LogSessionError(sessionId, ex);
|
||||
EnrolmentLog.LogSessionError(response.SessionId, ex);
|
||||
return new EnrolResponse
|
||||
{
|
||||
SessionId = sessionId,
|
||||
SessionId = response.SessionId,
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
EnrolmentLog.LogSessionError(sessionId, ex2);
|
||||
EnrolmentLog.LogSessionError(response.SessionId, ex2);
|
||||
throw ex2;
|
||||
}
|
||||
finally
|
||||
{
|
||||
EnrolmentLog.LogSessionFinished(sessionId);
|
||||
if (!response.IsPending)
|
||||
EnrolmentLog.LogSessionFinished(response.SessionId);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Devices.Enrolment;
|
||||
using Disco.Services.Web;
|
||||
using System;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Disco.Web.Areas.API.Controllers
|
||||
{
|
||||
public partial class EnrollmentController : AuthorizedDatabaseController
|
||||
{
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
[DiscoAuthorize(Claims.Device.Actions.EnrolDevices)]
|
||||
public virtual ActionResult ResolveSessionPending(string sessionId, bool approve, string reason)
|
||||
{
|
||||
WindowsDeviceEnrolment.ResolvePendingEnrollment(sessionId, approve, CurrentUser.UserId, reason);
|
||||
|
||||
return new HttpStatusCodeResult(200);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[DiscoAuthorize(Claims.Config.Enrolment.Configure)]
|
||||
public virtual ActionResult PendingTimeoutMinutes(int PendingTimeoutMinutes)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (PendingTimeoutMinutes > 0)
|
||||
{
|
||||
Database.DiscoConfiguration.Bootstrapper.PendingTimeout = TimeSpan.FromMinutes(PendingTimeoutMinutes);
|
||||
Database.SaveChanges();
|
||||
return Json("OK", JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("The pending timeout must be greater than zero");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Json($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,8 @@ namespace Disco.Web.Areas.Config.Controllers
|
||||
{
|
||||
var m = new Models.Enrolment.IndexModel()
|
||||
{
|
||||
MacSshUsername = Database.DiscoConfiguration.Bootstrapper.MacSshUsername
|
||||
MacSshUsername = Database.DiscoConfiguration.Bootstrapper.MacSshUsername,
|
||||
PendingTimeoutMinutes = (int)Database.DiscoConfiguration.Bootstrapper.PendingTimeout.TotalMinutes,
|
||||
};
|
||||
|
||||
// UI Extensions
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
using Disco.Models.UI.Config.Enrolment;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace Disco.Web.Areas.Config.Models.Enrolment
|
||||
{
|
||||
public class IndexModel : ConfigEnrolmentIndexModel
|
||||
{
|
||||
public string MacSshUsername { get; set; }
|
||||
public int PendingTimeoutMinutes { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -84,9 +84,9 @@
|
||||
}
|
||||
@if (Authorization.Has(Claims.Config.Enrolment.Show))
|
||||
{
|
||||
<i class="fa fa-cog"></i>@Html.ActionLinkClass("Enrolment", MVC.Config.Enrolment.Index(), "config")
|
||||
<i class="fa fa-cog"></i>@Html.ActionLinkClass("Enrollment", MVC.Config.Enrolment.Index(), "config")
|
||||
<div class="pageMenuBlurb">
|
||||
Configure Enrolment settings including secure credentials.
|
||||
Configure Enrollment settings including secure credentials.
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -592,14 +592,14 @@ WriteLiteral("></i>");
|
||||
#line hidden
|
||||
|
||||
#line 87 "..\..\Areas\Config\Views\Config\Index.cshtml"
|
||||
Write(Html.ActionLinkClass("Enrolment", MVC.Config.Enrolment.Index(), "config"));
|
||||
Write(Html.ActionLinkClass("Enrollment", MVC.Config.Enrolment.Index(), "config"));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 87 "..\..\Areas\Config\Views\Config\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
@@ -608,8 +608,8 @@ WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" class=\"pageMenuBlurb\"");
|
||||
|
||||
WriteLiteral(">\r\n Configure Enrolment settings including secure cred" +
|
||||
"entials.\r\n </div>\r\n");
|
||||
WriteLiteral(">\r\n Configure Enrollment settings including secure cre" +
|
||||
"dentials.\r\n </div>\r\n");
|
||||
|
||||
|
||||
#line 91 "..\..\Areas\Config\Views\Config\Index.cshtml"
|
||||
@@ -961,14 +961,14 @@ WriteLiteral(" class=\"fa fa-cloud-download info\"");
|
||||
|
||||
WriteLiteral("></i>\r\n <div>An updated version of Disco is available</div>\r\n <a");
|
||||
|
||||
WriteAttribute("href", Tuple.Create(" href=\"", 8211), Tuple.Create("\"", 8247)
|
||||
WriteAttribute("href", Tuple.Create(" href=\"", 8213), Tuple.Create("\"", 8249)
|
||||
|
||||
#line 155 "..\..\Areas\Config\Views\Config\Index.cshtml"
|
||||
, Tuple.Create(Tuple.Create("", 8218), Tuple.Create<System.Object, System.Int32>(Model.UpdateResponse.UrlLink
|
||||
, Tuple.Create(Tuple.Create("", 8220), Tuple.Create<System.Object, System.Int32>(Model.UpdateResponse.UrlLink
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
, 8218), false)
|
||||
, 8220), false)
|
||||
);
|
||||
|
||||
WriteLiteral(" class=\"button small alert\"");
|
||||
|
||||
@@ -5,20 +5,98 @@
|
||||
var canConfig = Authorization.Has(Claims.Config.Enrolment.Configure);
|
||||
var canShowStatus = Authorization.Has(Claims.Config.Enrolment.ShowStatus);
|
||||
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrolment");
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrollment");
|
||||
}
|
||||
<div class="form" style="width: 530px;">
|
||||
<h2>Apple Mac Secure Enrol</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Username:
|
||||
<th>
|
||||
Pending Timeout:
|
||||
</th>
|
||||
<td>@if (canConfig)
|
||||
<td>
|
||||
@if (canConfig)
|
||||
{
|
||||
@Html.TextBoxFor(model => model.MacSshUsername)
|
||||
@AjaxHelpers.AjaxSave()
|
||||
@AjaxHelpers.AjaxLoader()
|
||||
<script type="text/javascript">
|
||||
@Html.TextBoxFor(model => model.PendingTimeoutMinutes, new { type = "number", min = "1" })
|
||||
@AjaxHelpers.AjaxSave()
|
||||
@AjaxHelpers.AjaxLoader()
|
||||
<span> minutes <span class="smallText">(default: 30)</span></span>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
var $DOM = $('#PendingTimeoutMinutes');
|
||||
var $DOMAjaxSave = $DOM.next('.ajaxSave');
|
||||
$DOM
|
||||
.watermark('Minutes')
|
||||
.focus(function () { $DOM.select() })
|
||||
.keydown(function (e) {
|
||||
$DOMAjaxSave.show();
|
||||
if (e.which == 13) {
|
||||
$(this).blur();
|
||||
}
|
||||
}).blur(function () {
|
||||
$DOMAjaxSave.hide();
|
||||
})
|
||||
.change(function () {
|
||||
$DOMAjaxSave.hide();
|
||||
var $ajaxLoading = $DOMAjaxSave.next('.ajaxLoading').show();
|
||||
var data = { PendingTimeoutMinutes: parseInt($DOM.val()) };
|
||||
if (data.PendingTimeoutMinutes <= 0) {
|
||||
alert('Pending Timeout must be greater than zero');
|
||||
$ajaxLoading.hide();
|
||||
return;
|
||||
} else {
|
||||
$.ajax({
|
||||
url: '@Url.Action(MVC.API.Enrollment.PendingTimeoutMinutes())',
|
||||
dataType: 'json',
|
||||
method: 'POST',
|
||||
data: data,
|
||||
success: function (d) {
|
||||
if (d == 'OK') {
|
||||
$ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
|
||||
} else {
|
||||
$ajaxLoading.hide();
|
||||
alert('Unable to update pending timeout: ' + d);
|
||||
}
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
alert('Unable to update pending timeout: ' + textStatus);
|
||||
$ajaxLoading.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
}
|
||||
else
|
||||
{
|
||||
@TimeSpan.FromMinutes(Model.PendingTimeoutMinutes)
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<span class="smallText">
|
||||
If a device enrollment is not automatically approved it will remain pending until the timeout is reached.
|
||||
Pending enrollments can be approved manually from the Enrollment Status page.
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="form" style="width: 530px; margin-top: 15px">
|
||||
<h2>Apple Mac Secure Enroll</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
||||
Username:
|
||||
</th>
|
||||
<td>
|
||||
@if (canConfig)
|
||||
{
|
||||
@Html.TextBoxFor(model => model.MacSshUsername)
|
||||
@AjaxHelpers.AjaxSave()
|
||||
@AjaxHelpers.AjaxLoader()
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
var $DOM = $('#MacSshUsername');
|
||||
var $DOMAjaxSave = $DOM.next('.ajaxSave');
|
||||
@@ -56,31 +134,33 @@
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(Model.MacSshUsername))
|
||||
{
|
||||
<span class="smallMessage"><None Specified></span>
|
||||
<span class="smallMessage"><None Specified></span>
|
||||
}
|
||||
else
|
||||
{
|
||||
@Model.MacSshUsername
|
||||
@Model.MacSshUsername
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Password:
|
||||
<th>
|
||||
Password:
|
||||
</th>
|
||||
<td>@if (canConfig)
|
||||
<td>
|
||||
@if (canConfig)
|
||||
{
|
||||
<input id="MacSshPassword" type="password" />
|
||||
@AjaxHelpers.AjaxSave()
|
||||
@AjaxHelpers.AjaxLoader()
|
||||
<script type="text/javascript">
|
||||
<input id="MacSshPassword" type="password" />
|
||||
@AjaxHelpers.AjaxSave()
|
||||
@AjaxHelpers.AjaxLoader()
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
var $DOM = $('#MacSshPassword');
|
||||
var $DOMAjaxSave = $DOM.next('.ajaxSave');
|
||||
@@ -118,32 +198,36 @@
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
}
|
||||
else
|
||||
{
|
||||
<text>********</text>
|
||||
<text>********</text>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<span class="smallText"><strong>Instructions:</strong> The above credentials must be
|
||||
able to connect to the requesting Apple Mac client via <a target="_blank" href="http://en.wikipedia.org/wiki/Secure_Shell">SSH</a>. Enter/Script the following command:</span>
|
||||
<span class="smallText">
|
||||
<strong>Instructions:</strong> The above credentials must be
|
||||
able to connect to the requesting Apple Mac client via <a target="_blank" href="http://en.wikipedia.org/wiki/Secure_Shell">SSH</a>. Enter/Script the following command:
|
||||
</span>
|
||||
<div class="code">
|
||||
curl <a target="_blank" href="http://disco:9292/Services/Client/Unauthenticated/MacSecureEnrol">http://disco:9292/Services/Client/Unauthenticated/MacSecureEnrol</a>
|
||||
</div>
|
||||
<span class="smallText">This url will return a <a target="_blank" href="http://json.org/">JSON</a> response containing basic information about the enrolment.</span><br />
|
||||
<span class="smallMessage">This command makes use of <a target="_blank" href="http://curl.haxx.se/">cURL</a> (bundled with OSX). Other methods can also trigger a Mac Secure Enrol,
|
||||
<span class="smallText">This url will return a <a target="_blank" href="http://json.org/">JSON</a> response containing basic information about the enrollment.</span><br />
|
||||
<span class="smallMessage">
|
||||
This command makes use of <a target="_blank" href="http://curl.haxx.se/">cURL</a> (bundled with OSX). Other methods can also trigger a Mac Secure Enroll,
|
||||
such as an anchor (<span class="code"><a></span>) or <span class="code"><script></span>
|
||||
tag embedded on the organisation's intranet.</span>
|
||||
tag embedded on the organisation's intranet.
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@if (canShowStatus && Authorization.Has(Claims.Config.Logging.Show))
|
||||
{
|
||||
<h2>Live Enrolment Logging</h2>
|
||||
<h2>Live Enrollment Logging</h2>
|
||||
@Html.Partial(MVC.Config.Shared.Views.LogEvents, new Disco.Web.Areas.Config.Models.Shared.LogEventsModel()
|
||||
{
|
||||
IsLive = true,
|
||||
@@ -160,6 +244,6 @@
|
||||
}
|
||||
@if (canShowStatus)
|
||||
{
|
||||
@Html.ActionLinkButton("Enrolment Status", MVC.Config.Enrolment.Status())
|
||||
@Html.ActionLinkButton("Enrollment Status", MVC.Config.Enrolment.Status())
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Disco.Web.Areas.Config.Views.Enrolment
|
||||
var canConfig = Authorization.Has(Claims.Config.Enrolment.Configure);
|
||||
var canShowStatus = Authorization.Has(Claims.Config.Enrolment.ShowStatus);
|
||||
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrolment");
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrollment");
|
||||
|
||||
|
||||
#line default
|
||||
@@ -62,60 +62,238 @@ WriteLiteral(" class=\"form\"");
|
||||
|
||||
WriteLiteral(" style=\"width: 530px;\"");
|
||||
|
||||
WriteLiteral(">\r\n <h2>Apple Mac Secure Enrol</h2>\r\n <table>\r\n <tr>\r\n <t" +
|
||||
"h>Username:\r\n </th>\r\n <td>");
|
||||
WriteLiteral(">\r\n <table>\r\n <tr>\r\n <th>\r\n Pending Timeout:\r" +
|
||||
"\n </th>\r\n <td>\r\n");
|
||||
|
||||
|
||||
#line 16 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 17 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 17 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
if (canConfig)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 18 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Html.TextBoxFor(model => model.MacSshUsername));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 18 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 19 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(AjaxHelpers.AjaxSave());
|
||||
Write(Html.TextBoxFor(model => model.PendingTimeoutMinutes, new { type = "number", min = "1" }));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 19 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 20 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(AjaxHelpers.AjaxSave());
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 20 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 21 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(AjaxHelpers.AjaxLoader());
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 21 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <span> minutes <span");
|
||||
|
||||
WriteLiteral(" class=\"smallText\"");
|
||||
|
||||
WriteLiteral(">(default: 30)</span></span>\r\n");
|
||||
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(@">
|
||||
$(function () {
|
||||
var $DOM = $('#PendingTimeoutMinutes');
|
||||
var $DOMAjaxSave = $DOM.next('.ajaxSave');
|
||||
$DOM
|
||||
.watermark('Minutes')
|
||||
.focus(function () { $DOM.select() })
|
||||
.keydown(function (e) {
|
||||
$DOMAjaxSave.show();
|
||||
if (e.which == 13) {
|
||||
$(this).blur();
|
||||
}
|
||||
}).blur(function () {
|
||||
$DOMAjaxSave.hide();
|
||||
})
|
||||
.change(function () {
|
||||
$DOMAjaxSave.hide();
|
||||
var $ajaxLoading = $DOMAjaxSave.next('.ajaxLoading').show();
|
||||
var data = { PendingTimeoutMinutes: parseInt($DOM.val()) };
|
||||
if (data.PendingTimeoutMinutes <= 0) {
|
||||
alert('Pending Timeout must be greater than zero');
|
||||
$ajaxLoading.hide();
|
||||
return;
|
||||
} else {
|
||||
$.ajax({
|
||||
url: '");
|
||||
|
||||
|
||||
#line 48 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Url.Action(MVC.API.Enrollment.PendingTimeoutMinutes()));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(@"',
|
||||
dataType: 'json',
|
||||
method: 'POST',
|
||||
data: data,
|
||||
success: function (d) {
|
||||
if (d == 'OK') {
|
||||
$ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
|
||||
} else {
|
||||
$ajaxLoading.hide();
|
||||
alert('Unable to update pending timeout: ' + d);
|
||||
}
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
alert('Unable to update pending timeout: ' + textStatus);
|
||||
$ajaxLoading.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
");
|
||||
|
||||
|
||||
#line 69 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 72 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(TimeSpan.FromMinutes(Model.PendingTimeoutMinutes));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 72 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" </td>\r\n </tr>\r\n <tr>\r\n <td");
|
||||
|
||||
WriteLiteral(" colspan=\"2\"");
|
||||
|
||||
WriteLiteral(">\r\n <span");
|
||||
|
||||
WriteLiteral(" class=\"smallText\"");
|
||||
|
||||
WriteLiteral(@">
|
||||
If a device enrollment is not automatically approved it will remain pending until the timeout is reached.
|
||||
Pending enrollments can be approved manually from the Enrollment Status page.
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div");
|
||||
|
||||
WriteLiteral(" class=\"form\"");
|
||||
|
||||
WriteLiteral(" style=\"width: 530px; margin-top: 15px\"");
|
||||
|
||||
WriteLiteral(">\r\n <h2>Apple Mac Secure Enroll</h2>\r\n <table>\r\n <tr>\r\n <" +
|
||||
"th>\r\n Username:\r\n </th>\r\n <td>\r\n");
|
||||
|
||||
|
||||
#line 94 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 20 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(AjaxHelpers.AjaxLoader());
|
||||
#line 94 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
if (canConfig)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 96 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Html.TextBoxFor(model => model.MacSshUsername));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 20 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
#line 96 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 97 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(AjaxHelpers.AjaxSave());
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <script");
|
||||
|
||||
#line 97 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 98 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(AjaxHelpers.AjaxLoader());
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 98 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
@@ -142,7 +320,7 @@ WriteLiteral(@">
|
||||
url: '");
|
||||
|
||||
|
||||
#line 41 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 119 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Url.Action(MVC.API.Bootstrapper.MacSshUsername()));
|
||||
|
||||
|
||||
@@ -166,11 +344,11 @@ WriteLiteral(@"',
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
");
|
||||
|
||||
|
||||
#line 60 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 138 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -180,49 +358,55 @@ WriteLiteral(@"',
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <span");
|
||||
WriteLiteral(" <span");
|
||||
|
||||
WriteLiteral(" class=\"smallMessage\"");
|
||||
|
||||
WriteLiteral("><None Specified></span>\r\n");
|
||||
|
||||
|
||||
#line 66 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 144 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 69 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Model.MacSshUsername);
|
||||
#line 147 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Model.MacSshUsername);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 69 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
#line 147 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" </td>\r\n </tr>\r\n\r\n <tr>\r\n <th>Password:\r\n " +
|
||||
" </th>\r\n <td>");
|
||||
WriteLiteral(" </td>\r\n </tr>\r\n\r\n <tr>\r\n <th>\r\n " +
|
||||
" Password:\r\n </th>\r\n <td>\r\n");
|
||||
|
||||
|
||||
#line 78 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 158 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 158 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
if (canConfig)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <input");
|
||||
WriteLiteral(" <input");
|
||||
|
||||
WriteLiteral(" id=\"MacSshPassword\"");
|
||||
|
||||
@@ -231,40 +415,40 @@ WriteLiteral(" type=\"password\"");
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
|
||||
#line 81 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
#line 161 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 81 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(AjaxHelpers.AjaxSave());
|
||||
#line 161 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(AjaxHelpers.AjaxSave());
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 81 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
#line 161 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 82 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(AjaxHelpers.AjaxLoader());
|
||||
#line 162 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(AjaxHelpers.AjaxLoader());
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 82 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
#line 162 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <script");
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
@@ -291,7 +475,7 @@ WriteLiteral(@">
|
||||
url: '");
|
||||
|
||||
|
||||
#line 103 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 183 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Url.Action(MVC.API.Bootstrapper.MacSshPassword()));
|
||||
|
||||
|
||||
@@ -315,11 +499,11 @@ WriteLiteral(@"',
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
");
|
||||
|
||||
|
||||
#line 122 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 202 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -327,14 +511,14 @@ WriteLiteral(@"',
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" ");
|
||||
WriteLiteral(" ");
|
||||
|
||||
WriteLiteral("********");
|
||||
|
||||
WriteLiteral("\r\n");
|
||||
|
||||
|
||||
#line 126 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 206 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
}
|
||||
|
||||
|
||||
@@ -348,14 +532,16 @@ WriteLiteral(">\r\n <span");
|
||||
|
||||
WriteLiteral(" class=\"smallText\"");
|
||||
|
||||
WriteLiteral("><strong>Instructions:</strong> The above credentials must be\r\n " +
|
||||
" able to connect to the requesting Apple Mac client via <a");
|
||||
WriteLiteral(">\r\n <strong>Instructions:</strong> The above credentials must " +
|
||||
"be\r\n able to connect to the requesting Apple Mac client via <" +
|
||||
"a");
|
||||
|
||||
WriteLiteral(" target=\"_blank\"");
|
||||
|
||||
WriteLiteral(" href=\"http://en.wikipedia.org/wiki/Secure_Shell\"");
|
||||
|
||||
WriteLiteral(">SSH</a>. Enter/Script the following command:</span>\r\n <div");
|
||||
WriteLiteral(">SSH</a>. Enter/Script the following command:\r\n </span>\r\n " +
|
||||
" <div");
|
||||
|
||||
WriteLiteral(" class=\"code\"");
|
||||
|
||||
@@ -376,19 +562,19 @@ WriteLiteral(" target=\"_blank\"");
|
||||
|
||||
WriteLiteral(" href=\"http://json.org/\"");
|
||||
|
||||
WriteLiteral(">JSON</a> response containing basic information about the enrolment.</span><br />" +
|
||||
"\r\n <span");
|
||||
WriteLiteral(">JSON</a> response containing basic information about the enrollment.</span><br /" +
|
||||
">\r\n <span");
|
||||
|
||||
WriteLiteral(" class=\"smallMessage\"");
|
||||
|
||||
WriteLiteral(">This command makes use of <a");
|
||||
WriteLiteral(">\r\n This command makes use of <a");
|
||||
|
||||
WriteLiteral(" target=\"_blank\"");
|
||||
|
||||
WriteLiteral(" href=\"http://curl.haxx.se/\"");
|
||||
|
||||
WriteLiteral(">cURL</a> (bundled with OSX). Other methods can also trigger a Mac Secure Enrol,\r" +
|
||||
"\n such as an anchor (<span");
|
||||
WriteLiteral(">cURL</a> (bundled with OSX). Other methods can also trigger a Mac Secure Enroll," +
|
||||
"\r\n such as an anchor (<span");
|
||||
|
||||
WriteLiteral(" class=\"code\"");
|
||||
|
||||
@@ -397,26 +583,27 @@ WriteLiteral("><a></span>) or <span");
|
||||
WriteLiteral(" class=\"code\"");
|
||||
|
||||
WriteLiteral("><script></span>\r\n tag embedded on the organisation\'s in" +
|
||||
"tranet.</span>\r\n </td>\r\n </tr>\r\n </table>\r\n</div>\r\n");
|
||||
"tranet.\r\n </span>\r\n </td>\r\n </tr>\r\n </table>" +
|
||||
"\r\n</div>\r\n");
|
||||
|
||||
|
||||
#line 144 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 228 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
if (canShowStatus && Authorization.Has(Claims.Config.Logging.Show))
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <h2>Live Enrolment Logging</h2>\r\n");
|
||||
WriteLiteral(" <h2>Live Enrollment Logging</h2>\r\n");
|
||||
|
||||
|
||||
#line 147 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 231 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 147 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 231 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Html.Partial(MVC.Config.Shared.Views.LogEvents, new Disco.Web.Areas.Config.Models.Shared.LogEventsModel()
|
||||
{
|
||||
IsLive = true,
|
||||
@@ -430,7 +617,7 @@ Write(Html.Partial(MVC.Config.Shared.Views.LogEvents, new Disco.Web.Areas.Config
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 154 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 238 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
}
|
||||
|
||||
@@ -444,13 +631,13 @@ WriteLiteral(" class=\"actionBar\"");
|
||||
WriteLiteral(">\r\n");
|
||||
|
||||
|
||||
#line 157 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 241 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 157 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 241 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
if (Authorization.Has(Claims.Config.Enrolment.DownloadBootstrapper))
|
||||
{
|
||||
|
||||
@@ -458,14 +645,14 @@ WriteLiteral(">\r\n");
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 159 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 243 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Html.ActionLinkButton("Download Bootstrapper", MVC.Services.Client.Bootstrapper()));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 159 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 243 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
}
|
||||
|
||||
@@ -475,7 +662,7 @@ WriteLiteral(">\r\n");
|
||||
WriteLiteral(" ");
|
||||
|
||||
|
||||
#line 161 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
#line 245 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
if (canShowStatus)
|
||||
{
|
||||
|
||||
@@ -483,15 +670,15 @@ WriteLiteral(" ");
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 163 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Html.ActionLinkButton("Enrolment Status", MVC.Config.Enrolment.Status()));
|
||||
#line 247 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
Write(Html.ActionLinkButton("Enrollment Status", MVC.Config.Enrolment.Status()));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 163 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
#line 247 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,27 +1,47 @@
|
||||
@{
|
||||
Authorization.Require(Claims.Config.Enrolment.ShowStatus);
|
||||
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrolment", MVC.Config.Enrolment.Index(), "Status");
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrollment", MVC.Config.Enrolment.Index(), "Status");
|
||||
Html.BundleDeferred("~/ClientScripts/Modules/Knockout");
|
||||
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
|
||||
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-Isotope");
|
||||
}
|
||||
<div id="enrolStatus">
|
||||
<div id="noSessions" data-bind="visible: noSessions">
|
||||
<h2>No enrolment sessions today</h2>
|
||||
<h2>No enrollment sessions today</h2>
|
||||
</div>
|
||||
<div id="sessions" data-bind="visible: !noSessions(), foreach: { data: sessions, afterRender: sessionRendered, afterAdd: sessionAdded }" style="display: none">
|
||||
<div class="session" data-bind="style: { backgroundImage: deviceModelImageUrl }, click: select">
|
||||
<h3>
|
||||
<span data-bind="text: title"></span>
|
||||
<span class="details" data-bind="text: '(' + deviceModelDescription() + ')'"></span>
|
||||
<i class="fa fa-exclamation-circle" data-bind="visible: isPending"></i>
|
||||
</h3>
|
||||
<p class="sessionStart" data-bind="text: startTime"></p>
|
||||
<p class="sessionStatus" data-bind="text: progressStatus"></p>
|
||||
<div data-bind="visible: !sessionEnded(), progressValue: progressValue" class="sessionProgress"></div>
|
||||
<div data-bind="visible: !sessionEnded() && progressValue >= 0, progressValue: progressValue" class="sessionProgress"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dialogSession" data-bind="with: currentSession">
|
||||
<div class="sessionProgress clearfix">
|
||||
<p class="sessionStart" data-bind="text: startTime"></p>
|
||||
<p class="sessionStatus" data-bind="text: progressStatus"></p>
|
||||
<div data-bind="visible: !sessionEnded() && progressValue >= 0, progressValue: progressValue"></div>
|
||||
<div id="formResolveSessionPending" data-bind="visible: isPending">
|
||||
@using (Html.BeginForm(MVC.API.Enrollment.ResolveSessionPending(), FormMethod.Post))
|
||||
{
|
||||
@Html.AntiForgeryToken();
|
||||
<input type="hidden" name="sessionId" data-bind="value: id" />
|
||||
<div class="reason">
|
||||
<input type="text" name="reason" placeholder="Reason (optional)" />
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button type="button" value="True" class="button">Approve</button>
|
||||
<button type="button" value="False" class="button">Reject</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="sessionHeader clearfix" data-bind="style: { backgroundImage: deviceModelImageUrl }">
|
||||
<h2><a href="" target="_blank" data-bind="text: title, attr: { href: deviceUrl }"></a></h2>
|
||||
<h3 data-bind="text: deviceModelDescription"></h3>
|
||||
@@ -48,11 +68,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="sessionProgress clearfix">
|
||||
<p class="sessionStart" data-bind="text: startTime"></p>
|
||||
<p class="sessionStatus" data-bind="text: progressStatus"></p>
|
||||
<div data-bind="visible: !sessionEnded(), progressValue: progressValue"></div>
|
||||
</div>
|
||||
<div class="sessionInfoContainer clearfix">
|
||||
<div class="sessionInfoMessages">
|
||||
<table class="logEventsViewport">
|
||||
@@ -134,7 +149,9 @@
|
||||
function sessionViewModel(id) {
|
||||
var self = this;
|
||||
|
||||
self.id = id;
|
||||
self.title = ko.observable(id);
|
||||
self.isPending = ko.observable(false);
|
||||
self.messages = ko.observableArray();
|
||||
self.console = ko.observableArray();
|
||||
self.serialNumber = ko.observable();
|
||||
@@ -187,7 +204,7 @@
|
||||
self.select = function (e, d) {
|
||||
vm.currentSession(self);
|
||||
hostDialogSessions.dialog('open');
|
||||
hostDialogSessions.dialog('option', 'title', 'Device Enrolment: ' + self.title());
|
||||
hostDialogSessions.dialog('option', 'title', 'Device Enrollment: ' + self.title());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,15 +245,38 @@
|
||||
if (log.Arguments.length >= 10 && log.Arguments[9])
|
||||
session.deviceModelId(log.Arguments[9]);
|
||||
break;
|
||||
case 14: // SessionPending
|
||||
session.isPending(true);
|
||||
session.messages.unshift(log);
|
||||
session.progressValue(-1);
|
||||
session.progressStatus('Pending enrollment approval');
|
||||
break;
|
||||
case 15: // SessionPendingApproved
|
||||
session.isPending(false);
|
||||
session.messages.unshift(log);
|
||||
session.progressValue(-1);
|
||||
session.progressStatus('Enrollment approval, waiting for client');
|
||||
break;
|
||||
case 16: // SessionPendingRejected
|
||||
session.isPending(false);
|
||||
session.messages.unshift(log);
|
||||
session.progressValue(-1);
|
||||
session.progressStatus('Enrollment rejected, waiting for client');
|
||||
break;
|
||||
case 17: // SessionContinuing
|
||||
session.isPending(false);
|
||||
session.messages.unshift(log);
|
||||
break;
|
||||
case 20: // SessionFinished
|
||||
session.sessionEnded(true);
|
||||
session.isPending(false);
|
||||
if (session.hasError())
|
||||
session.progressStatus('Enrolment Finished with an Error');
|
||||
session.progressStatus('Enrollment Finished with an Error');
|
||||
else
|
||||
if (session.hasWarning())
|
||||
session.progressStatus('Enrolment Finished with a Warning');
|
||||
session.progressStatus('Enrollment Finished with a Warning');
|
||||
else
|
||||
session.progressStatus('Enrolment Finished Successfully');
|
||||
session.progressStatus('Enrollment Finished Successfully');
|
||||
session.messages.unshift(log);
|
||||
break;
|
||||
case 21: // SessionDiagnosticInformation
|
||||
@@ -357,6 +397,20 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
$('#dialogSession').on('click', '#formResolveSessionPending button', function (e) {
|
||||
const $button = $(this);
|
||||
const $form = $button.closest('form');
|
||||
const body = new FormData($form[0]);
|
||||
body.append('approve', $button.val());
|
||||
fetch($form.attr('action'), {
|
||||
method: 'POST',
|
||||
body: body
|
||||
}).then(function (response) {
|
||||
if (!response.ok) {
|
||||
alert('Failed to resolve pending session: ' + response.statusText);
|
||||
}
|
||||
});
|
||||
});
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Disco.Web.Areas.Config.Views.Enrolment
|
||||
|
||||
Authorization.Require(Claims.Config.Enrolment.ShowStatus);
|
||||
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrolment", MVC.Config.Enrolment.Index(), "Status");
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrollment", MVC.Config.Enrolment.Index(), "Status");
|
||||
Html.BundleDeferred("~/ClientScripts/Modules/Knockout");
|
||||
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
|
||||
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-Isotope");
|
||||
@@ -66,7 +66,7 @@ WriteLiteral(" id=\"noSessions\"");
|
||||
|
||||
WriteLiteral(" data-bind=\"visible: noSessions\"");
|
||||
|
||||
WriteLiteral(">\r\n <h2>No enrolment sessions today</h2>\r\n </div>\r\n <div");
|
||||
WriteLiteral(">\r\n <h2>No enrollment sessions today</h2>\r\n </div>\r\n <div");
|
||||
|
||||
WriteLiteral(" id=\"sessions\"");
|
||||
|
||||
@@ -91,7 +91,13 @@ WriteLiteral(" class=\"details\"");
|
||||
|
||||
WriteLiteral(" data-bind=\"text: \'(\' + deviceModelDescription() + \')\'\"");
|
||||
|
||||
WriteLiteral("></span>\r\n </h3>\r\n <p");
|
||||
WriteLiteral("></span>\r\n <i");
|
||||
|
||||
WriteLiteral(" class=\"fa fa-exclamation-circle\"");
|
||||
|
||||
WriteLiteral(" data-bind=\"visible: isPending\"");
|
||||
|
||||
WriteLiteral("></i>\r\n </h3>\r\n <p");
|
||||
|
||||
WriteLiteral(" class=\"sessionStart\"");
|
||||
|
||||
@@ -105,7 +111,8 @@ WriteLiteral(" data-bind=\"text: progressStatus\"");
|
||||
|
||||
WriteLiteral("></p>\r\n <div");
|
||||
|
||||
WriteLiteral(" data-bind=\"visible: !sessionEnded(), progressValue: progressValue\"");
|
||||
WriteLiteral(" data-bind=\"visible: !sessionEnded() && progressValue >= 0, progressValue: progre" +
|
||||
"ssValue\"");
|
||||
|
||||
WriteLiteral(" class=\"sessionProgress\"");
|
||||
|
||||
@@ -117,6 +124,116 @@ WriteLiteral(" data-bind=\"with: currentSession\"");
|
||||
|
||||
WriteLiteral(">\r\n <div");
|
||||
|
||||
WriteLiteral(" class=\"sessionProgress clearfix\"");
|
||||
|
||||
WriteLiteral(">\r\n <p");
|
||||
|
||||
WriteLiteral(" class=\"sessionStart\"");
|
||||
|
||||
WriteLiteral(" data-bind=\"text: startTime\"");
|
||||
|
||||
WriteLiteral("></p>\r\n <p");
|
||||
|
||||
WriteLiteral(" class=\"sessionStatus\"");
|
||||
|
||||
WriteLiteral(" data-bind=\"text: progressStatus\"");
|
||||
|
||||
WriteLiteral("></p>\r\n <div");
|
||||
|
||||
WriteLiteral(" data-bind=\"visible: !sessionEnded() && progressValue >= 0, progressValue: progre" +
|
||||
"ssValue\"");
|
||||
|
||||
WriteLiteral("></div>\r\n <div");
|
||||
|
||||
WriteLiteral(" id=\"formResolveSessionPending\"");
|
||||
|
||||
WriteLiteral(" data-bind=\"visible: isPending\"");
|
||||
|
||||
WriteLiteral(">\r\n");
|
||||
|
||||
|
||||
#line 31 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 31 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
using (Html.BeginForm(MVC.API.Enrollment.ResolveSessionPending(), FormMethod.Post))
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 33 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
Write(Html.AntiForgeryToken());
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 33 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <input");
|
||||
|
||||
WriteLiteral(" type=\"hidden\"");
|
||||
|
||||
WriteLiteral(" name=\"sessionId\"");
|
||||
|
||||
WriteLiteral(" data-bind=\"value: id\"");
|
||||
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" class=\"reason\"");
|
||||
|
||||
WriteLiteral(">\r\n <input");
|
||||
|
||||
WriteLiteral(" type=\"text\"");
|
||||
|
||||
WriteLiteral(" name=\"reason\"");
|
||||
|
||||
WriteLiteral(" placeholder=\"Reason (optional)\"");
|
||||
|
||||
WriteLiteral(" />\r\n </div>\r\n");
|
||||
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" class=\"buttons\"");
|
||||
|
||||
WriteLiteral(">\r\n <button");
|
||||
|
||||
WriteLiteral(" type=\"button\"");
|
||||
|
||||
WriteLiteral(" value=\"True\"");
|
||||
|
||||
WriteLiteral(" class=\"button\"");
|
||||
|
||||
WriteLiteral(">Approve</button>\r\n <button");
|
||||
|
||||
WriteLiteral(" type=\"button\"");
|
||||
|
||||
WriteLiteral(" value=\"False\"");
|
||||
|
||||
WriteLiteral(" class=\"button\"");
|
||||
|
||||
WriteLiteral(">Reject</button>\r\n </div>\r\n");
|
||||
|
||||
|
||||
#line 42 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" </div>\r\n </div>\r\n <div");
|
||||
|
||||
WriteLiteral(" class=\"sessionHeader clearfix\"");
|
||||
|
||||
WriteLiteral(" data-bind=\"style: { backgroundImage: deviceModelImageUrl }\"");
|
||||
@@ -181,26 +298,6 @@ WriteLiteral(" data-bind=\"text: sessionDeviceInfo().Arguments[6] + \' \' + sess
|
||||
WriteLiteral("></td>\r\n </tr>\r\n </table>\r\n </div>\r\n <div" +
|
||||
"");
|
||||
|
||||
WriteLiteral(" class=\"sessionProgress clearfix\"");
|
||||
|
||||
WriteLiteral(">\r\n <p");
|
||||
|
||||
WriteLiteral(" class=\"sessionStart\"");
|
||||
|
||||
WriteLiteral(" data-bind=\"text: startTime\"");
|
||||
|
||||
WriteLiteral("></p>\r\n <p");
|
||||
|
||||
WriteLiteral(" class=\"sessionStatus\"");
|
||||
|
||||
WriteLiteral(" data-bind=\"text: progressStatus\"");
|
||||
|
||||
WriteLiteral("></p>\r\n <div");
|
||||
|
||||
WriteLiteral(" data-bind=\"visible: !sessionEnded(), progressValue: progressValue\"");
|
||||
|
||||
WriteLiteral("></div>\r\n </div>\r\n <div");
|
||||
|
||||
WriteLiteral(" class=\"sessionInfoContainer clearfix\"");
|
||||
|
||||
WriteLiteral(">\r\n <div");
|
||||
@@ -309,7 +406,7 @@ WriteLiteral(@">
|
||||
var deviceBaseUrl = '");
|
||||
|
||||
|
||||
#line 107 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
#line 122 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
Write(Url.Action(MVC.Device.Show()));
|
||||
|
||||
|
||||
@@ -318,7 +415,7 @@ WriteLiteral(@">
|
||||
WriteLiteral("/\'\r\n var deviceModelImageUrl = \'");
|
||||
|
||||
|
||||
#line 108 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
#line 123 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
Write(Url.Action(MVC.API.DeviceModel.Image()));
|
||||
|
||||
|
||||
@@ -327,7 +424,7 @@ WriteLiteral("/\'\r\n var deviceModelImageUrl = \'");
|
||||
WriteLiteral("/\'\r\n var iconWarningUrl = \'url(");
|
||||
|
||||
|
||||
#line 109 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
#line 124 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
Write(Links.ClientSource.Style.Images.Status.warning32_png);
|
||||
|
||||
|
||||
@@ -336,7 +433,7 @@ WriteLiteral("/\'\r\n var iconWarningUrl = \'url(");
|
||||
WriteLiteral(")\';\r\n var iconErrorUrl = \'url(");
|
||||
|
||||
|
||||
#line 110 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
#line 125 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
Write(Links.ClientSource.Style.Images.Status.fail32_png);
|
||||
|
||||
|
||||
@@ -352,39 +449,40 @@ WriteLiteral(")\';\r\n\r\n function pageViewModel() {\r\n var
|
||||
"nction (e, d) {\r\n if (self.isotopeInited) {\r\n " +
|
||||
"hostSessions.isotope(\'reloadItems\').isotope({ sortBy: \'original-order\' });\r\n " +
|
||||
" }\r\n };\r\n }\r\n function sessionViewModel(id) " +
|
||||
"{\r\n var self = this;\r\n\r\n self.title = ko.observable(id);\r\n" +
|
||||
" self.messages = ko.observableArray();\r\n self.console = ko" +
|
||||
".observableArray();\r\n self.serialNumber = ko.observable();\r\n " +
|
||||
" self.sessionDeviceInfo = ko.observable();\r\n self.progressStatus = " +
|
||||
"ko.observable();\r\n self.progressValue = ko.observable();\r\n " +
|
||||
" self.startTime = ko.observable();\r\n self.sessionEnded = ko.observabl" +
|
||||
"e(false);\r\n self.progressbar = null;\r\n self.hasError = ko." +
|
||||
"observable(false);\r\n self.hasWarning = ko.observable(false);\r\n " +
|
||||
" self.deviceModelId = ko.observable();\r\n self.deviceModelDescript" +
|
||||
"ion = ko.computed(function () {\r\n var deviceModelId = self.device" +
|
||||
"ModelId();\r\n var sessionDeviceInfo = self.sessionDeviceInfo();\r\n " +
|
||||
" if (deviceModelId) {\r\n var dm = deviceModels[d" +
|
||||
"eviceModelId];\r\n if (dm) {\r\n if (dm.De" +
|
||||
"scription)\r\n return dm.Description;\r\n " +
|
||||
" else\r\n return dm.Manufacturer + \' \' + dm.Mode" +
|
||||
"l;\r\n }\r\n }\r\n if (sessionDeviceI" +
|
||||
"nfo) {\r\n return sessionDeviceInfo.Arguments[6] + \' \' + sessio" +
|
||||
"nDeviceInfo.Arguments[7];\r\n }\r\n });\r\n self." +
|
||||
"deviceUrl = ko.computed(function () {\r\n var serialNumber = self.s" +
|
||||
"erialNumber();\r\n if (serialNumber)\r\n return de" +
|
||||
"viceBaseUrl + serialNumber;\r\n else\r\n return nu" +
|
||||
"ll;\r\n });\r\n self.deviceModelImageUrl = ko.computed(functio" +
|
||||
"n () {\r\n var deviceModelImage;\r\n if (self.deviceMo" +
|
||||
"delId())\r\n deviceModelImage = \'url(\' + deviceModelImageUrl + " +
|
||||
"self.deviceModelId() + \')\';\r\n else\r\n deviceMod" +
|
||||
"elImage = \'url(\' + deviceModelImageUrl + \')\';\r\n if (self.hasError" +
|
||||
"())\r\n return iconErrorUrl + \', \' + deviceModelImage;\r\n " +
|
||||
" else\r\n if (self.hasWarning())\r\n " +
|
||||
" return iconWarningUrl + \', \' + deviceModelImage;\r\n else\r\n " +
|
||||
" return \'none, \' + deviceModelImage;\r\n });\r\n " +
|
||||
" self.select = function (e, d) {\r\n vm.currentSession(self" +
|
||||
");\r\n hostDialogSessions.dialog(\'open\');\r\n hostDial" +
|
||||
"ogSessions.dialog(\'option\', \'title\', \'Device Enrolment: \' + self.title());\r\n " +
|
||||
"{\r\n var self = this;\r\n\r\n self.id = id;\r\n self.t" +
|
||||
"itle = ko.observable(id);\r\n self.isPending = ko.observable(false);\r\n " +
|
||||
" self.messages = ko.observableArray();\r\n self.console = ko." +
|
||||
"observableArray();\r\n self.serialNumber = ko.observable();\r\n " +
|
||||
" self.sessionDeviceInfo = ko.observable();\r\n self.progressStatus = k" +
|
||||
"o.observable();\r\n self.progressValue = ko.observable();\r\n " +
|
||||
"self.startTime = ko.observable();\r\n self.sessionEnded = ko.observable" +
|
||||
"(false);\r\n self.progressbar = null;\r\n self.hasError = ko.o" +
|
||||
"bservable(false);\r\n self.hasWarning = ko.observable(false);\r\n " +
|
||||
" self.deviceModelId = ko.observable();\r\n self.deviceModelDescripti" +
|
||||
"on = ko.computed(function () {\r\n var deviceModelId = self.deviceM" +
|
||||
"odelId();\r\n var sessionDeviceInfo = self.sessionDeviceInfo();\r\n " +
|
||||
" if (deviceModelId) {\r\n var dm = deviceModels[de" +
|
||||
"viceModelId];\r\n if (dm) {\r\n if (dm.Des" +
|
||||
"cription)\r\n return dm.Description;\r\n " +
|
||||
" else\r\n return dm.Manufacturer + \' \' + dm.Model" +
|
||||
";\r\n }\r\n }\r\n if (sessionDeviceIn" +
|
||||
"fo) {\r\n return sessionDeviceInfo.Arguments[6] + \' \' + session" +
|
||||
"DeviceInfo.Arguments[7];\r\n }\r\n });\r\n self.d" +
|
||||
"eviceUrl = ko.computed(function () {\r\n var serialNumber = self.se" +
|
||||
"rialNumber();\r\n if (serialNumber)\r\n return dev" +
|
||||
"iceBaseUrl + serialNumber;\r\n else\r\n return nul" +
|
||||
"l;\r\n });\r\n self.deviceModelImageUrl = ko.computed(function" +
|
||||
" () {\r\n var deviceModelImage;\r\n if (self.deviceMod" +
|
||||
"elId())\r\n deviceModelImage = \'url(\' + deviceModelImageUrl + s" +
|
||||
"elf.deviceModelId() + \')\';\r\n else\r\n deviceMode" +
|
||||
"lImage = \'url(\' + deviceModelImageUrl + \')\';\r\n if (self.hasError(" +
|
||||
"))\r\n return iconErrorUrl + \', \' + deviceModelImage;\r\n " +
|
||||
" else\r\n if (self.hasWarning())\r\n " +
|
||||
" return iconWarningUrl + \', \' + deviceModelImage;\r\n else\r\n " +
|
||||
" return \'none, \' + deviceModelImage;\r\n });\r\n " +
|
||||
" self.select = function (e, d) {\r\n vm.currentSession(self)" +
|
||||
";\r\n hostDialogSessions.dialog(\'open\');\r\n hostDialo" +
|
||||
"gSessions.dialog(\'option\', \'title\', \'Device Enrollment: \' + self.title());\r\n " +
|
||||
" }\r\n }\r\n\r\n function parseLog(log) {\r\n if (log.Mo" +
|
||||
"duleId === 50 && log.Arguments && log.Arguments.length > 0) {\r\n /" +
|
||||
"/ find session\r\n var sessionId = log.Arguments[0];\r\n " +
|
||||
@@ -413,33 +511,50 @@ WriteLiteral(")\';\r\n\r\n function pageViewModel() {\r\n var
|
||||
"ion.sessionDeviceInfo(log);\r\n if (log.Arguments.lengt" +
|
||||
"h >= 10 && log.Arguments[9])\r\n session.deviceMode" +
|
||||
"lId(log.Arguments[9]);\r\n break;\r\n " +
|
||||
" case 20: // SessionFinished\r\n session.sessionEnde" +
|
||||
"d(true);\r\n if (session.hasError())\r\n " +
|
||||
" session.progressStatus(\'Enrolment Finished with an Error\');\r\n " +
|
||||
" else\r\n if (session.hasWar" +
|
||||
"ning())\r\n session.progressStatus(\'Enrolment F" +
|
||||
"inished with a Warning\');\r\n else\r\n " +
|
||||
" session.progressStatus(\'Enrolment Finished Successfully\');\r" +
|
||||
"\n session.messages.unshift(log);\r\n " +
|
||||
" break;\r\n case 21: // SessionDiagnosticInformatio" +
|
||||
"n\r\n session.console.push(log);\r\n " +
|
||||
" break;\r\n case 22: // SessionWarning\r\n " +
|
||||
" session.hasWarning(true);\r\n session.me" +
|
||||
"ssages.unshift(log);\r\n break;\r\n " +
|
||||
" case 23: // SessionError\r\n case 24: // SessionErrorWith" +
|
||||
"Inner\r\n case 25: // SessionClientError\r\n " +
|
||||
" session.hasError(true);\r\n session.messages" +
|
||||
".unshift(log);\r\n break;\r\n defa" +
|
||||
"ult:\r\n session.messages.unshift(log);\r\n " +
|
||||
" }\r\n }\r\n }\r\n }\r\n function init() {\r" +
|
||||
"\n hostDialogSessions.dialog({\r\n modal: true,\r\n " +
|
||||
" height: 574,\r\n width: 900,\r\n resizable: fa" +
|
||||
"lse,\r\n autoOpen: false\r\n });\r\n //hostDialog" +
|
||||
"SessionsProgress.progressbar();\r\n\r\n // Create View Model\r\n " +
|
||||
" vm = new pageViewModel();\r\n $.ajax({\r\n url: \'");
|
||||
" case 14: // SessionPending\r\n session.isPending(tr" +
|
||||
"ue);\r\n session.messages.unshift(log);\r\n " +
|
||||
" session.progressValue(-1);\r\n session.pr" +
|
||||
"ogressStatus(\'Pending enrollment approval\');\r\n break;" +
|
||||
"\r\n case 15: // SessionPendingApproved\r\n " +
|
||||
" session.isPending(false);\r\n session.message" +
|
||||
"s.unshift(log);\r\n session.progressValue(-1);\r\n " +
|
||||
" session.progressStatus(\'Enrollment approval, waiting for cl" +
|
||||
"ient\');\r\n break;\r\n case 16: //" +
|
||||
" SessionPendingRejected\r\n session.isPending(false);\r\n" +
|
||||
" session.messages.unshift(log);\r\n " +
|
||||
" session.progressValue(-1);\r\n session.progress" +
|
||||
"Status(\'Enrollment rejected, waiting for client\');\r\n " +
|
||||
"break;\r\n case 17: // SessionContinuing\r\n " +
|
||||
" session.isPending(false);\r\n session.messag" +
|
||||
"es.unshift(log);\r\n break;\r\n ca" +
|
||||
"se 20: // SessionFinished\r\n session.sessionEnded(true" +
|
||||
");\r\n session.isPending(false);\r\n " +
|
||||
" if (session.hasError())\r\n session.progress" +
|
||||
"Status(\'Enrollment Finished with an Error\');\r\n else\r\n" +
|
||||
" if (session.hasWarning())\r\n " +
|
||||
" session.progressStatus(\'Enrollment Finished with a Warning\');\r\n " +
|
||||
" else\r\n session." +
|
||||
"progressStatus(\'Enrollment Finished Successfully\');\r\n " +
|
||||
" session.messages.unshift(log);\r\n break;\r\n " +
|
||||
" case 21: // SessionDiagnosticInformation\r\n " +
|
||||
" session.console.push(log);\r\n break;\r\n " +
|
||||
" case 22: // SessionWarning\r\n session.hasWa" +
|
||||
"rning(true);\r\n session.messages.unshift(log);\r\n " +
|
||||
" break;\r\n case 23: // SessionError\r\n" +
|
||||
" case 24: // SessionErrorWithInner\r\n " +
|
||||
" case 25: // SessionClientError\r\n session.hasError(" +
|
||||
"true);\r\n session.messages.unshift(log);\r\n " +
|
||||
" break;\r\n default:\r\n " +
|
||||
" session.messages.unshift(log);\r\n }\r\n }\r\n" +
|
||||
" }\r\n }\r\n function init() {\r\n hostDialogSessi" +
|
||||
"ons.dialog({\r\n modal: true,\r\n height: 574,\r\n " +
|
||||
" width: 900,\r\n resizable: false,\r\n autoOp" +
|
||||
"en: false\r\n });\r\n //hostDialogSessionsProgress.progressbar" +
|
||||
"();\r\n\r\n // Create View Model\r\n vm = new pageViewModel();\r\n" +
|
||||
" $.ajax({\r\n url: \'");
|
||||
|
||||
|
||||
#line 274 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
#line 314 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
Write(Url.Action(MVC.API.DeviceModel.Index()));
|
||||
|
||||
|
||||
@@ -473,7 +588,7 @@ WriteLiteral(@"',
|
||||
url: '");
|
||||
|
||||
|
||||
#line 299 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
#line 339 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
Write(Url.Action(MVC.API.Logging.RetrieveEvents()));
|
||||
|
||||
|
||||
@@ -512,7 +627,7 @@ WriteLiteral(@"',
|
||||
$.connection.hub.qs = { LogModules: '");
|
||||
|
||||
|
||||
#line 329 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
#line 369 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
|
||||
Write(Disco.Services.Devices.Enrolment.EnrolmentLog.Current.LiveLogGroupName);
|
||||
|
||||
|
||||
@@ -537,7 +652,15 @@ WriteLiteral("\' };\r\n $.connection.hub.error(onHubFailed);\r\n\r\n
|
||||
" \'Close\': function () {\r\n " +
|
||||
" $(this).dialog(\'destroy\');\r\n }\r\n " +
|
||||
" }\r\n });\r\n }\r\n }" +
|
||||
"\r\n }\r\n init();\r\n });\r\n</script>\r\n");
|
||||
"\r\n }\r\n $(\'#dialogSession\').on(\'click\', \'#formResolveSessionPending" +
|
||||
" button\', function (e) {\r\n const $button = $(this);\r\n cons" +
|
||||
"t $form = $button.closest(\'form\');\r\n const body = new FormData($form[" +
|
||||
"0]);\r\n body.append(\'approve\', $button.val());\r\n fetch($for" +
|
||||
"m.attr(\'action\'), {\r\n method: \'POST\',\r\n body: body" +
|
||||
"\r\n }).then(function (response) {\r\n if (!response.ok) {" +
|
||||
"\r\n alert(\'Failed to resolve pending session: \' + response.sta" +
|
||||
"tusText);\r\n }\r\n });\r\n });\r\n init();\r\n " +
|
||||
" });\r\n</script>\r\n");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,6 +473,10 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.message {
|
||||
#enrolStatus #sessions .session > h3 span.details {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
#enrolStatus #sessions .session > h3 i {
|
||||
float: right;
|
||||
color: #F0A30A;
|
||||
}
|
||||
#enrolStatus #sessions .session > p.sessionStart {
|
||||
color: #888;
|
||||
font-size: 0.8em;
|
||||
@@ -489,7 +493,6 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.message {
|
||||
background-color: #DFE1F8;
|
||||
}
|
||||
#dialogSession .sessionHeader {
|
||||
width: 400px;
|
||||
float: left;
|
||||
padding: 0 0 0 134px;
|
||||
background-repeat: no-repeat, no-repeat;
|
||||
@@ -516,7 +519,8 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.message {
|
||||
}
|
||||
#dialogSession .sessionProgress {
|
||||
width: 320px;
|
||||
float: right;
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
text-align: right;
|
||||
}
|
||||
#dialogSession .sessionProgress > p.sessionStart {
|
||||
@@ -528,6 +532,9 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.message {
|
||||
overflow: hidden;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
#dialogSession .sessionProgress div.reason {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
#dialogSession .sessionInfoContainer > div {
|
||||
float: left;
|
||||
width: 428px;
|
||||
|
||||
@@ -479,6 +479,11 @@ div.logEventsViewport {
|
||||
span.details {
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
i {
|
||||
float: right;
|
||||
color: @ThemeAmber;
|
||||
}
|
||||
}
|
||||
|
||||
& > p.sessionStart {
|
||||
@@ -504,7 +509,6 @@ div.logEventsViewport {
|
||||
|
||||
#dialogSession {
|
||||
.sessionHeader {
|
||||
width: 400px;
|
||||
float: left;
|
||||
padding: 0 0 0 134px;
|
||||
background-repeat: no-repeat, no-repeat;
|
||||
@@ -535,7 +539,8 @@ div.logEventsViewport {
|
||||
|
||||
.sessionProgress {
|
||||
width: 320px;
|
||||
float: right;
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
text-align: right;
|
||||
|
||||
& > p.sessionStart {
|
||||
@@ -548,6 +553,10 @@ div.logEventsViewport {
|
||||
overflow: hidden;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
& div.reason {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.sessionInfoContainer {
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -97,6 +97,32 @@
|
||||
height: 50px;
|
||||
font-size: 0.6em;
|
||||
}
|
||||
#layout_PageHeading #pendingEnrollments {
|
||||
position: relative;
|
||||
float: right;
|
||||
border: 1px dashed #ddd;
|
||||
background-color: #fff;
|
||||
font-size: 0.6em;
|
||||
line-height: 1em;
|
||||
padding: 10px 10px 4px 70px;
|
||||
text-align: right;
|
||||
height: 50px;
|
||||
}
|
||||
#layout_PageHeading #pendingEnrollments i {
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
vertical-align: middle;
|
||||
margin-left: -75px;
|
||||
top: 8px;
|
||||
font-size: 50px;
|
||||
color: #e51400;
|
||||
}
|
||||
#layout_PageHeading #pendingEnrollments a.button {
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
#Jobs_Index_MyJobs {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,35 @@
|
||||
height: 50px;
|
||||
font-size: 0.6em;
|
||||
}
|
||||
|
||||
#pendingEnrollments {
|
||||
position: relative;
|
||||
float: right;
|
||||
border: 1px dashed #ddd;
|
||||
background-color: @white;
|
||||
font-size: 0.6em;
|
||||
line-height: 1em;
|
||||
padding: 10px 10px 4px 70px;
|
||||
text-align: right;
|
||||
height: 50px;
|
||||
|
||||
i {
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
vertical-align: middle;
|
||||
margin-left: -75px;
|
||||
top: 8px;
|
||||
font-size: 50px;
|
||||
color: @ButtonAlertColour;
|
||||
}
|
||||
|
||||
a.button {
|
||||
font-size: @FontSizeDefault;
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Jobs_Index_MyJobs {
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -4,6 +4,7 @@ using Disco.Models.Services.Jobs.JobLists;
|
||||
using Disco.Models.UI.Job;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Devices.Enrolment;
|
||||
using Disco.Services.Jobs;
|
||||
using Disco.Services.Jobs.JobLists;
|
||||
using Disco.Services.Jobs.JobQueues;
|
||||
@@ -46,6 +47,9 @@ namespace Disco.Web.Controllers
|
||||
if (Authorization.Has(Claims.Job.ShowDailyChart))
|
||||
m.DailyOpenedClosedStatistics = DailyOpenedClosed.Data(Database, true);
|
||||
|
||||
if (Authorization.Has(Claims.Device.Actions.EnrolDevices))
|
||||
m.PendingEnrollments = WindowsDeviceEnrolment.GetPendingEnrolments();
|
||||
|
||||
// UI Extensions
|
||||
UIExtensions.ExecuteExtensions<JobIndexModel>(this.ControllerContext, m);
|
||||
|
||||
|
||||
+17
-13
@@ -208,6 +208,7 @@
|
||||
<Compile Include="Areas\API\Controllers\AuthorizationRoleController.cs" />
|
||||
<Compile Include="Areas\API\Controllers\DocumentTemplatePackageController.cs" />
|
||||
<Compile Include="Areas\API\Controllers\DeviceFlagAssignmentController.cs" />
|
||||
<Compile Include="Areas\API\Controllers\EnrollmentController.cs" />
|
||||
<Compile Include="Areas\API\Controllers\UserFlagAssignmentController.cs" />
|
||||
<Compile Include="Areas\API\Controllers\DeviceFlagController.cs" />
|
||||
<Compile Include="Areas\API\Controllers\UserFlagController.cs" />
|
||||
@@ -678,6 +679,9 @@
|
||||
<Compile Include="Extensions\T4MVC\API.DocumentTemplatePackageController.generated.cs">
|
||||
<DependentUpon>T4MVC.tt</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Extensions\T4MVC\API.EnrollmentController.generated.cs">
|
||||
<DependentUpon>T4MVC.tt</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Extensions\T4MVC\Config.DeviceFlagController.generated.cs">
|
||||
<DependentUpon>T4MVC.tt</DependentUpon>
|
||||
</Compile>
|
||||
@@ -1339,30 +1343,30 @@
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>_DeviceGroupDocumentBulkGenerate.generated.cs</LastGenOutput>
|
||||
</None>
|
||||
<Content Include="Areas\Config\Views\DeviceFlag\Create.cshtml">
|
||||
<None Include="Areas\Config\Views\DeviceFlag\Create.cshtml">
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>Create.generated.cs</LastGenOutput>
|
||||
</Content>
|
||||
<Content Include="Areas\Config\Views\DeviceFlag\Export.cshtml">
|
||||
</None>
|
||||
<None Include="Areas\Config\Views\DeviceFlag\Export.cshtml">
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>Export.generated.cs</LastGenOutput>
|
||||
</Content>
|
||||
<Content Include="Areas\Config\Views\DeviceFlag\Index.cshtml">
|
||||
</None>
|
||||
<None Include="Areas\Config\Views\DeviceFlag\Index.cshtml">
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>Index.generated.cs</LastGenOutput>
|
||||
</Content>
|
||||
<Content Include="Areas\Config\Views\DeviceFlag\Show.cshtml">
|
||||
</None>
|
||||
<None Include="Areas\Config\Views\DeviceFlag\Show.cshtml">
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>Show.generated.cs</LastGenOutput>
|
||||
</Content>
|
||||
</None>
|
||||
<None Include="Areas\Config\Views\UserFlag\Create.cshtml">
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>Create.generated.cs</LastGenOutput>
|
||||
</None>
|
||||
<Content Include="Areas\Config\Views\UserFlag\Export.cshtml">
|
||||
<None Include="Areas\Config\Views\UserFlag\Export.cshtml">
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>Export.generated.cs</LastGenOutput>
|
||||
</Content>
|
||||
</None>
|
||||
<None Include="Areas\Config\Views\UserFlag\Index.cshtml">
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>Index.generated.cs</LastGenOutput>
|
||||
@@ -1505,7 +1509,7 @@
|
||||
<DependentUpon>Disco-DataTableHelpers.js</DependentUpon>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator\disco.documentgenerator.js" />
|
||||
<Content Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator\disco.documentgenerator.js" Condition=" '$(Configuration)' == 'Debug' " />
|
||||
<None Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator.js" />
|
||||
<Content Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator.js" Condition=" '$(Configuration)' == 'Debug' " />
|
||||
<Content Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator.min.js">
|
||||
@@ -1941,10 +1945,10 @@
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>AddOffline.generated.cs</LastGenOutput>
|
||||
</None>
|
||||
<Content Include="Views\Device\DeviceParts\_Flags.cshtml">
|
||||
<None Include="Views\Device\DeviceParts\_Flags.cshtml">
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>_Flags.generated.cs</LastGenOutput>
|
||||
</Content>
|
||||
</None>
|
||||
<None Include="Views\Device\ImportHeaders.cshtml">
|
||||
<Generator>RazorGenerator</Generator>
|
||||
<LastGenOutput>ImportHeaders.generated.cs</LastGenOutput>
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
// <auto-generated />
|
||||
// This file was generated by a T4 template.
|
||||
// Don't change it directly as your change would get overwritten. Instead, make changes
|
||||
// to the .tt file (i.e. the T4 template) and save it to regenerate this file.
|
||||
|
||||
// Make sure the compiler doesn't complain about missing Xml comments and CLS compliance
|
||||
// 0108: suppress "Foo hides inherited member Foo. Use the new keyword if hiding was intended." when a controller and its abstract parent are both processed
|
||||
// 0114: suppress "Foo.BarController.Baz()' hides inherited member 'Qux.BarController.Baz()'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." when an action (with an argument) overrides an action in a parent controller
|
||||
#pragma warning disable 1591, 3008, 3009, 0108, 0114
|
||||
#region T4MVC
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Mvc.Ajax;
|
||||
using System.Web.Mvc.Html;
|
||||
using System.Web.Routing;
|
||||
using T4MVC;
|
||||
namespace Disco.Web.Areas.API.Controllers
|
||||
{
|
||||
public partial class EnrollmentController
|
||||
{
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public EnrollmentController() { }
|
||||
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
protected EnrollmentController(Dummy d) { }
|
||||
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
protected RedirectToRouteResult RedirectToAction(ActionResult result)
|
||||
{
|
||||
var callInfo = result.GetT4MVCResult();
|
||||
return RedirectToRoute(callInfo.RouteValueDictionary);
|
||||
}
|
||||
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
protected RedirectToRouteResult RedirectToAction(Task<ActionResult> taskResult)
|
||||
{
|
||||
return RedirectToAction(taskResult.Result);
|
||||
}
|
||||
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
protected RedirectToRouteResult RedirectToActionPermanent(ActionResult result)
|
||||
{
|
||||
var callInfo = result.GetT4MVCResult();
|
||||
return RedirectToRoutePermanent(callInfo.RouteValueDictionary);
|
||||
}
|
||||
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
protected RedirectToRouteResult RedirectToActionPermanent(Task<ActionResult> taskResult)
|
||||
{
|
||||
return RedirectToActionPermanent(taskResult.Result);
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public virtual System.Web.Mvc.ActionResult ResolveSessionPending()
|
||||
{
|
||||
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.ResolveSessionPending);
|
||||
}
|
||||
[NonAction]
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public virtual System.Web.Mvc.ActionResult PendingTimeoutMinutes()
|
||||
{
|
||||
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.PendingTimeoutMinutes);
|
||||
}
|
||||
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public EnrollmentController Actions { get { return MVC.API.Enrollment; } }
|
||||
[GeneratedCode("T4MVC", "2.0")]
|
||||
public readonly string Area = "API";
|
||||
[GeneratedCode("T4MVC", "2.0")]
|
||||
public readonly string Name = "Enrollment";
|
||||
[GeneratedCode("T4MVC", "2.0")]
|
||||
public const string NameConst = "Enrollment";
|
||||
[GeneratedCode("T4MVC", "2.0")]
|
||||
static readonly ActionNamesClass s_actions = new ActionNamesClass();
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public ActionNamesClass ActionNames { get { return s_actions; } }
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public class ActionNamesClass
|
||||
{
|
||||
public readonly string ResolveSessionPending = "ResolveSessionPending";
|
||||
public readonly string PendingTimeoutMinutes = "PendingTimeoutMinutes";
|
||||
}
|
||||
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public class ActionNameConstants
|
||||
{
|
||||
public const string ResolveSessionPending = "ResolveSessionPending";
|
||||
public const string PendingTimeoutMinutes = "PendingTimeoutMinutes";
|
||||
}
|
||||
|
||||
|
||||
static readonly ActionParamsClass_ResolveSessionPending s_params_ResolveSessionPending = new ActionParamsClass_ResolveSessionPending();
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public ActionParamsClass_ResolveSessionPending ResolveSessionPendingParams { get { return s_params_ResolveSessionPending; } }
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public class ActionParamsClass_ResolveSessionPending
|
||||
{
|
||||
public readonly string sessionId = "sessionId";
|
||||
public readonly string approve = "approve";
|
||||
public readonly string reason = "reason";
|
||||
}
|
||||
static readonly ActionParamsClass_PendingTimeoutMinutes s_params_PendingTimeoutMinutes = new ActionParamsClass_PendingTimeoutMinutes();
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public ActionParamsClass_PendingTimeoutMinutes PendingTimeoutMinutesParams { get { return s_params_PendingTimeoutMinutes; } }
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public class ActionParamsClass_PendingTimeoutMinutes
|
||||
{
|
||||
public readonly string PendingTimeoutMinutes = "PendingTimeoutMinutes";
|
||||
}
|
||||
static readonly ViewsClass s_views = new ViewsClass();
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public ViewsClass Views { get { return s_views; } }
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public class ViewsClass
|
||||
{
|
||||
static readonly _ViewNamesClass s_ViewNames = new _ViewNamesClass();
|
||||
public _ViewNamesClass ViewNames { get { return s_ViewNames; } }
|
||||
public class _ViewNamesClass
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
|
||||
public partial class T4MVC_EnrollmentController : Disco.Web.Areas.API.Controllers.EnrollmentController
|
||||
{
|
||||
public T4MVC_EnrollmentController() : base(Dummy.Instance) { }
|
||||
|
||||
[NonAction]
|
||||
partial void ResolveSessionPendingOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string sessionId, bool approve, string reason);
|
||||
|
||||
[NonAction]
|
||||
public override System.Web.Mvc.ActionResult ResolveSessionPending(string sessionId, bool approve, string reason)
|
||||
{
|
||||
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.ResolveSessionPending);
|
||||
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "sessionId", sessionId);
|
||||
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "approve", approve);
|
||||
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "reason", reason);
|
||||
ResolveSessionPendingOverride(callInfo, sessionId, approve, reason);
|
||||
return callInfo;
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
partial void PendingTimeoutMinutesOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int PendingTimeoutMinutes);
|
||||
|
||||
[NonAction]
|
||||
public override System.Web.Mvc.ActionResult PendingTimeoutMinutes(int PendingTimeoutMinutes)
|
||||
{
|
||||
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.PendingTimeoutMinutes);
|
||||
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "PendingTimeoutMinutes", PendingTimeoutMinutes);
|
||||
PendingTimeoutMinutesOverride(callInfo, PendingTimeoutMinutes);
|
||||
return callInfo;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion T4MVC
|
||||
#pragma warning restore 1591, 3008, 3009, 0108, 0114
|
||||
@@ -62,6 +62,7 @@ namespace T4MVC
|
||||
public Disco.Web.Areas.API.Controllers.DeviceProfileController DeviceProfile = new Disco.Web.Areas.API.Controllers.T4MVC_DeviceProfileController();
|
||||
public Disco.Web.Areas.API.Controllers.DocumentTemplateController DocumentTemplate = new Disco.Web.Areas.API.Controllers.T4MVC_DocumentTemplateController();
|
||||
public Disco.Web.Areas.API.Controllers.DocumentTemplatePackageController DocumentTemplatePackage = new Disco.Web.Areas.API.Controllers.T4MVC_DocumentTemplatePackageController();
|
||||
public Disco.Web.Areas.API.Controllers.EnrollmentController Enrollment = new Disco.Web.Areas.API.Controllers.T4MVC_EnrollmentController();
|
||||
public Disco.Web.Areas.API.Controllers.ExpressionsController Expressions = new Disco.Web.Areas.API.Controllers.T4MVC_ExpressionsController();
|
||||
public Disco.Web.Areas.API.Controllers.JobController Job = new Disco.Web.Areas.API.Controllers.T4MVC_JobController();
|
||||
public Disco.Web.Areas.API.Controllers.JobPreferencesController JobPreferences = new Disco.Web.Areas.API.Controllers.T4MVC_JobPreferencesController();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Disco.Models.Services.Job.Statistics;
|
||||
using Disco.Models.ClientServices;
|
||||
using Disco.Models.Services.Job.Statistics;
|
||||
using Disco.Models.Services.Jobs.JobLists;
|
||||
using Disco.Models.UI.Job;
|
||||
using System.Collections.Generic;
|
||||
@@ -9,6 +10,7 @@ namespace Disco.Web.Models.Job
|
||||
{
|
||||
public JobTableModel MyJobs { get; set; }
|
||||
public JobTableModel StaleJobs { get; set; }
|
||||
public List<EnrolResponse> PendingEnrollments { get; set; }
|
||||
|
||||
public List<DailyOpenedClosedItem> DailyOpenedClosedStatistics { get; set; }
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<div id="chartHostJobDailyOpenedClosed" style="height: 175px;">
|
||||
</div>
|
||||
@{
|
||||
var jsonData = new HtmlString(Json.Encode(Model.DailyOpenedClosedStatistics));
|
||||
var jsonData = new HtmlString(Json.Encode(Model.DailyOpenedClosedStatistics));
|
||||
}
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
@@ -144,4 +144,20 @@
|
||||
<h2>Stale Jobs (@Model.StaleJobs.Items.Count())</h2>
|
||||
@Html.Partial(MVC.Shared.Views._JobTable, Model.StaleJobs, new ViewDataDictionary())
|
||||
</div>
|
||||
}
|
||||
@if (Model.PendingEnrollments != null && Model.PendingEnrollments.Count > 0 && Authorization.Has(Claims.Device.Actions.EnrolDevices))
|
||||
{
|
||||
<div id="pendingEnrollments">
|
||||
<i class="fa fa-exclamation-circle info"></i>
|
||||
<div>There are device enrollments pending approval.</div>
|
||||
<a href="@Url.Action(MVC.Config.Enrolment.Status())" class="button small alert" target="_blank">View Enrollments</a>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
var layout_PageHeading = $('#layout_PageHeading').height(80);
|
||||
$('#pendingEnrollments')
|
||||
.detach()
|
||||
.appendTo(layout_PageHeading);
|
||||
});
|
||||
</script>
|
||||
}
|
||||
@@ -131,7 +131,7 @@ WriteLiteral(">\r\n </div>\r\n");
|
||||
|
||||
#line 24 "..\..\Views\Job\Index.cshtml"
|
||||
|
||||
var jsonData = new HtmlString(Json.Encode(Model.DailyOpenedClosedStatistics));
|
||||
var jsonData = new HtmlString(Json.Encode(Model.DailyOpenedClosedStatistics));
|
||||
|
||||
|
||||
#line default
|
||||
@@ -174,34 +174,34 @@ WriteLiteral(">\r\n (function () {\r\n var cha
|
||||
"top\',\r\n y: 0,\r\n " +
|
||||
" floating: true,\r\n borderWidth: 0,\r\n " +
|
||||
" itemStyle: {\r\n " +
|
||||
" color: \'#333\',\n fontWeight: \'normal" +
|
||||
"\'\r\n }\r\n },\r\n " +
|
||||
" xAxis: {\r\n type" +
|
||||
": \'datetime\',\r\n tickInterval: 7 * 24 * 3600 *" +
|
||||
" 1000, // week\r\n tickWidth: 1,\r\n " +
|
||||
" gridLineWidth: 1,\r\n da" +
|
||||
"teTimeLabelFormats: {\r\n week: \'%e %b\'\r\n " +
|
||||
" }\r\n },\r\n " +
|
||||
" yAxis: [{\r\n title: {" +
|
||||
"\r\n text: null\r\n " +
|
||||
" },\r\n labels: {\r\n " +
|
||||
" enabled: false\r\n },\r\n " +
|
||||
" min: 0\r\n }, {\r\n " +
|
||||
" title: {\r\n " +
|
||||
" text: null\r\n },\r\n " +
|
||||
" labels: {\r\n enabled: false\r\n" +
|
||||
" },\r\n min:" +
|
||||
" 0\r\n }],\r\n series:" +
|
||||
" [{\r\n name: \'Total Open Jobs\',\r\n " +
|
||||
" data: dataTotalOpenJobs,\r\n " +
|
||||
" yAxis: 1\r\n }, {\r\n " +
|
||||
" name: \'Closed Jobs\',\r\n data: dataClo" +
|
||||
"sedJobs\r\n }, {\r\n " +
|
||||
" name: \'Opened Jobs\',\r\n data: dataOpenedJob" +
|
||||
"s\r\n }],\r\n credits:" +
|
||||
" {\r\n enabled: false\r\n " +
|
||||
" }\r\n });\r\n });\r\n " +
|
||||
" }\r\n chartData = $.parseJSON(\'");
|
||||
" color: \'#333\',\r\n fontWeight: \'norma" +
|
||||
"l\'\r\n }\r\n },\r\n " +
|
||||
" xAxis: {\r\n typ" +
|
||||
"e: \'datetime\',\r\n tickInterval: 7 * 24 * 3600 " +
|
||||
"* 1000, // week\r\n tickWidth: 1,\r\n " +
|
||||
" gridLineWidth: 1,\r\n d" +
|
||||
"ateTimeLabelFormats: {\r\n week: \'%e %b\'\r\n " +
|
||||
" }\r\n },\r\n " +
|
||||
" yAxis: [{\r\n title: " +
|
||||
"{\r\n text: null\r\n " +
|
||||
" },\r\n labels: {\r\n " +
|
||||
" enabled: false\r\n },\r\n " +
|
||||
" min: 0\r\n }, {\r\n" +
|
||||
" title: {\r\n " +
|
||||
" text: null\r\n },\r\n " +
|
||||
" labels: {\r\n enabled: false\r" +
|
||||
"\n },\r\n min" +
|
||||
": 0\r\n }],\r\n series" +
|
||||
": [{\r\n name: \'Total Open Jobs\',\r\n " +
|
||||
" data: dataTotalOpenJobs,\r\n " +
|
||||
" yAxis: 1\r\n }, {\r\n " +
|
||||
" name: \'Closed Jobs\',\r\n data: dataCl" +
|
||||
"osedJobs\r\n }, {\r\n " +
|
||||
" name: \'Opened Jobs\',\r\n data: dataOpenedJo" +
|
||||
"bs\r\n }],\r\n credits" +
|
||||
": {\r\n enabled: false\r\n " +
|
||||
" }\r\n });\r\n });\r\n " +
|
||||
" }\r\n chartData = $.parseJSON(\'");
|
||||
|
||||
|
||||
#line 126 "..\..\Views\Job\Index.cshtml"
|
||||
@@ -300,6 +300,53 @@ WriteLiteral("\r\n </div>\r\n");
|
||||
|
||||
#line 147 "..\..\Views\Job\Index.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 148 "..\..\Views\Job\Index.cshtml"
|
||||
if (Model.PendingEnrollments != null && Model.PendingEnrollments.Count > 0 && Authorization.Has(Claims.Device.Actions.EnrolDevices))
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" id=\"pendingEnrollments\"");
|
||||
|
||||
WriteLiteral(">\r\n <i");
|
||||
|
||||
WriteLiteral(" class=\"fa fa-exclamation-circle info\"");
|
||||
|
||||
WriteLiteral("></i>\r\n <div>There are device enrollments pending approval.</div>\r\n " +
|
||||
" <a");
|
||||
|
||||
WriteAttribute("href", Tuple.Create(" href=\"", 6766), Tuple.Create("\"", 6815)
|
||||
|
||||
#line 153 "..\..\Views\Job\Index.cshtml"
|
||||
, Tuple.Create(Tuple.Create("", 6773), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.Config.Enrolment.Status())
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
, 6773), false)
|
||||
);
|
||||
|
||||
WriteLiteral(" class=\"button small alert\"");
|
||||
|
||||
WriteLiteral(" target=\"_blank\"");
|
||||
|
||||
WriteLiteral(">View Enrollments</a>\r\n </div>\r\n");
|
||||
|
||||
WriteLiteral(" <script>\r\n $(function () {\r\n var layout_PageHeading = $(\'#l" +
|
||||
"ayout_PageHeading\').height(80);\r\n $(\'#pendingEnrollments\')\r\n " +
|
||||
" .detach()\r\n .appendTo(layout_PageHeading);\r\n });\r\n " +
|
||||
" </script>\r\n");
|
||||
|
||||
|
||||
#line 163 "..\..\Views\Job\Index.cshtml"
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
@@ -137,4 +137,14 @@ Global
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {1CCC4DCB-653B-464B-B05D-285032B28DC4}
|
||||
EndGlobalSection
|
||||
GlobalSection(AutomaticVersions) = postSolution
|
||||
UpdateAssemblyVersion = True
|
||||
UpdateAssemblyFileVersion = True
|
||||
UpdateAssemblyInfoVersion = False
|
||||
AssemblyVersionSettings = None.None.DateStamp.TimeStamp
|
||||
AssemblyFileVersionSettings = None.None.DateStamp.TimeStamp
|
||||
UpdatePackageVersion = False
|
||||
AssemblyInfoVersionType = SettingsVersion
|
||||
InheritWinAppVersionFrom = None
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Reference in New Issue
Block a user