From 6139b499a96165ac5c4ccb4900fd36c76622ea1f Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Wed, 25 Feb 2015 01:39:59 -0800 Subject: [PATCH 01/21] RDS Help desk computer group added --- .../RemoteDesktopServicesProxy.cs | 78 ++++++++++ .../RemoteDesktopServicesController.cs | 72 ++++++++- .../esRemoteDesktopServices.asmx.cs | 6 + .../IRemoteDesktopServices.cs | 1 + .../RdsCollectionSettings.cs | 5 +- .../RemoteApplication.cs | 1 + .../Windows2012.cs | 147 ++++++++++++++++-- .../RemoteDesktopServicesProxy.cs | 55 +++++++ .../RemoteDesktopServices.asmx.cs | 16 ++ .../WebsitePanel_SharedResources.ascx.resx | 3 + .../RDSEditCollectionSettings.ascx.resx | 9 ++ .../RDS/RDSCreateCollection.ascx.cs | 17 +- .../RDS/RDSEditCollectionSettings.ascx | 37 +++++ .../RDS/RDSEditCollectionSettings.ascx.cs | 11 +- ...RDSEditCollectionSettings.ascx.designer.cs | 63 ++++++++ .../RDS/UserControls/RDSCollectionApps.ascx | 9 +- 16 files changed, 505 insertions(+), 25 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/RemoteDesktopServicesProxy.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/RemoteDesktopServicesProxy.cs index 6ba412b9..3214d80d 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/RemoteDesktopServicesProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/RemoteDesktopServicesProxy.cs @@ -118,6 +118,8 @@ namespace WebsitePanel.EnterpriseServer { private System.Threading.SendOrPostCallback SaveRdsCollectionLocalAdminsOperationCompleted; + private System.Threading.SendOrPostCallback InstallSessionHostsCertificateOperationCompleted; + /// public esRemoteDesktopServices() { this.Url = "http://localhost:9002/esRemoteDesktopServices.asmx"; @@ -255,6 +257,9 @@ namespace WebsitePanel.EnterpriseServer { /// public event SaveRdsCollectionLocalAdminsCompletedEventHandler SaveRdsCollectionLocalAdminsCompleted; + /// + public event InstallSessionHostsCertificateCompletedEventHandler InstallSessionHostsCertificateCompleted; + /// [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/GetRdsCollection", RequestNamespace="http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace="http://smbsaas/websitepanel/enterpriseserver", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public RdsCollection GetRdsCollection(int collectionId) { @@ -2238,6 +2243,53 @@ namespace WebsitePanel.EnterpriseServer { } } + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/InstallSessionHostsCertificate", RequestNamespace="http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace="http://smbsaas/websitepanel/enterpriseserver", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public ResultObject InstallSessionHostsCertificate(int collectionId, [System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary")] byte[] certificate, string password) { + object[] results = this.Invoke("InstallSessionHostsCertificate", new object[] { + collectionId, + certificate, + password}); + return ((ResultObject)(results[0])); + } + + /// + public System.IAsyncResult BeginInstallSessionHostsCertificate(int collectionId, byte[] certificate, string password, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("InstallSessionHostsCertificate", new object[] { + collectionId, + certificate, + password}, callback, asyncState); + } + + /// + public ResultObject EndInstallSessionHostsCertificate(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((ResultObject)(results[0])); + } + + /// + public void InstallSessionHostsCertificateAsync(int collectionId, byte[] certificate, string password) { + this.InstallSessionHostsCertificateAsync(collectionId, certificate, password, null); + } + + /// + public void InstallSessionHostsCertificateAsync(int collectionId, byte[] certificate, string password, object userState) { + if ((this.InstallSessionHostsCertificateOperationCompleted == null)) { + this.InstallSessionHostsCertificateOperationCompleted = new System.Threading.SendOrPostCallback(this.OnInstallSessionHostsCertificateOperationCompleted); + } + this.InvokeAsync("InstallSessionHostsCertificate", new object[] { + collectionId, + certificate, + password}, this.InstallSessionHostsCertificateOperationCompleted, userState); + } + + private void OnInstallSessionHostsCertificateOperationCompleted(object arg) { + if ((this.InstallSessionHostsCertificateCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.InstallSessionHostsCertificateCompleted(this, new InstallSessionHostsCertificateCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// public new void CancelAsync(object userState) { base.CancelAsync(userState); @@ -3387,4 +3439,30 @@ namespace WebsitePanel.EnterpriseServer { } } } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void InstallSessionHostsCertificateCompletedEventHandler(object sender, InstallSessionHostsCertificateCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class InstallSessionHostsCertificateCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal InstallSessionHostsCertificateCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public ResultObject Result { + get { + this.RaiseExceptionIfNecessary(); + return ((ResultObject)(this.results[0])); + } + } + } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs index e1561f26..91f589c3 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs @@ -278,6 +278,51 @@ namespace WebsitePanel.EnterpriseServer return SaveRdsCollectionLocalAdminsInternal(users, collectionId); } + public static ResultObject InstallSessionHostsCertificate(int collectionId, byte[] certificate, string password) + { + return InstallSessionHostsCertificateInternal(collectionId, certificate, password); + } + + private static ResultObject InstallSessionHostsCertificateInternal(int collectionId, byte[] certificate, string password) + { + var result = TaskManager.StartResultTask("REMOTE_DESKTOP_SERVICES", "INSTALL_CERTIFICATE"); + + try + { + var collection = ObjectUtils.FillObjectFromDataReader(DataProvider.GetRDSCollectionById(collectionId)); + Organization org = OrganizationController.GetOrganization(collection.ItemId); + + if (org == null) + { + result.IsSuccess = false; + result.AddError("", new NullReferenceException("Organization not found")); + return result; + } + + var rds = GetRemoteDesktopServices(GetRemoteDesktopServiceID(org.PackageId)); + var servers = ObjectUtils.CreateListFromDataReader(DataProvider.GetRDSServersByCollectionId(collection.Id)).ToList(); + + rds.InstallCertificate(certificate, password, servers.Select(s => s.FqdName).ToArray()); + } + catch (Exception ex) + { + throw TaskManager.WriteError(ex); + } + finally + { + if (!result.IsSuccess) + { + TaskManager.CompleteResultTask(result); + } + else + { + TaskManager.CompleteResultTask(); + } + } + + return result; + } + private static RdsCollection GetRdsCollectionInternal(int collectionId) { var collection = ObjectUtils.FillObjectFromDataReader(DataProvider.GetRDSCollectionById(collectionId)); @@ -372,9 +417,25 @@ namespace WebsitePanel.EnterpriseServer private static RdsCollectionSettings GetRdsCollectionSettingsInternal(int collectionId) { - var collection = ObjectUtils.FillObjectFromDataReader(DataProvider.GetRDSCollectionById(collectionId)); - - return ObjectUtils.FillObjectFromDataReader(DataProvider.GetRdsCollectionSettingsByCollectionId(collectionId)); + var collection = ObjectUtils.FillObjectFromDataReader(DataProvider.GetRDSCollectionById(collectionId)); + var settings = ObjectUtils.FillObjectFromDataReader(DataProvider.GetRdsCollectionSettingsByCollectionId(collectionId)); + + if (settings.SecurityLayer == null) + { + settings.SecurityLayer = SecurityLayerValues.Negotiate.ToString(); + } + + if (settings.EncryptionLevel == null) + { + settings.EncryptionLevel = EncryptionLevel.ClientCompatible.ToString(); + } + + if (settings.AuthenticateUsingNLA == null) + { + settings.AuthenticateUsingNLA = true; + } + + return settings; } private static List GetOrganizationRdsCollectionsInternal(int itemId) @@ -426,7 +487,10 @@ namespace WebsitePanel.EnterpriseServer ClientPrinterRedirected = true, ClientPrinterAsDefault = true, RDEasyPrintDriverEnabled = true, - MaxRedirectedMonitors = 16 + MaxRedirectedMonitors = 16, + EncryptionLevel = EncryptionLevel.ClientCompatible.ToString(), + SecurityLayer = SecurityLayerValues.Negotiate.ToString(), + AuthenticateUsingNLA = true }; rds.CreateCollection(org.OrganizationId, collection); diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esRemoteDesktopServices.asmx.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esRemoteDesktopServices.asmx.cs index e6391df1..8cd3ecdb 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esRemoteDesktopServices.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esRemoteDesktopServices.asmx.cs @@ -325,5 +325,11 @@ namespace WebsitePanel.EnterpriseServer { return RemoteDesktopServicesController.SaveRdsCollectionLocalAdmins(users, collectionId); } + + [WebMethod] + public ResultObject InstallSessionHostsCertificate(int collectionId, byte[] certificate, string password) + { + return RemoteDesktopServicesController.InstallSessionHostsCertificate(collectionId, certificate, password); + } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs index 9ecc03eb..133eb575 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs @@ -78,5 +78,6 @@ namespace WebsitePanel.Providers.RemoteDesktopServices List GetRdsCollectionLocalAdmins(string hostName); void MoveRdsServerToTenantOU(string hostName, string organizationId); void RemoveRdsServerFromTenantOU(string hostName, string organizationId); + void InstallCertificate(byte[] certificate, string password, List hostNames); } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsCollectionSettings.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsCollectionSettings.cs index 5827ecc6..2ccae36a 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsCollectionSettings.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsCollectionSettings.cs @@ -21,6 +21,9 @@ namespace WebsitePanel.Providers.RemoteDesktopServices public bool ClientPrinterRedirected { get; set; } public bool ClientPrinterAsDefault { get; set; } public bool RDEasyPrintDriverEnabled { get; set; } - public int MaxRedirectedMonitors { get; set; } + public int MaxRedirectedMonitors { get; set; } + public string SecurityLayer { get; set; } + public string EncryptionLevel { get; set; } + public bool AuthenticateUsingNLA { get; set; } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RemoteApplication.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RemoteApplication.cs index 300f8b47..b0bda452 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RemoteApplication.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RemoteApplication.cs @@ -36,5 +36,6 @@ namespace WebsitePanel.Providers.RemoteDesktopServices public string FileVirtualPath { get; set; } public bool ShowInWebAccess { get; set; } public string RequiredCommandLine { get; set; } + public string[] Users { get; set; } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs index 515250c5..af65e3c0 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs @@ -70,8 +70,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices private const string WspAdministratorsGroupName = "WSP-Administrators"; private const string WspAdministratorsGroupDescription = "WSP Administrators"; private const string RdsServersOU = "RDSServers"; - private const uint ADS_GROUP_TYPE_UNIVERSAL_GROUP = 0x00000008; - private const uint ADS_GROUP_TYPE_SECURITY_ENABLED = 0x80000000; + private const string RDSHelpDeskComputerGroup = "Websitepanel-RDSHelpDesk-Computer"; #endregion @@ -309,6 +308,11 @@ namespace WebsitePanel.Providers.RemoteDesktopServices //ActiveDirectoryUtils.AddObjectToGroup(GetComputerPath(ConnectionBroker), GetComputerGroupPath(organizationId, collection.Name)); } + if (!ActiveDirectoryUtils.AdObjectExists(GetHelpDeskComputerGroupPath())) + { + ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskComputerGroup); + } + if (!ActiveDirectoryUtils.AdObjectExists(GetUsersGroupPath(organizationId, collection.Name))) { //Create user group @@ -561,6 +565,11 @@ namespace WebsitePanel.Providers.RemoteDesktopServices ExecuteShellCommand(runSpace, cmd, false); + if (!ActiveDirectoryUtils.AdObjectExists(GetHelpDeskComputerGroupPath())) + { + ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskComputerGroup); + } + AddComputerToCollectionAdComputerGroup(organizationId, collectionName, server); } catch (Exception e) @@ -1134,32 +1143,103 @@ namespace WebsitePanel.Providers.RemoteDesktopServices #region SSL - public void InstallCertificate(byte[] certificate, string password, string hostName) + public void InstallCertificate(byte[] certificate, string password, List hostNames) { Runspace runspace = null; try - { + { + var guid = Guid.NewGuid(); var x509Cert = new X509Certificate2(certificate, password, X509KeyStorageFlags.Exportable); + //var content = x509Cert.Export(X509ContentType.Pfx); + var filePath = SaveCertificate(certificate, guid); runspace = OpenRunspace(); - CopyCertificateFile(certificate, hostName, runspace); + + foreach (var hostName in hostNames) + { + var destinationPath = string.Format("\\\\{0}\\c$\\{1}.pfx", hostName, guid); + var errors = CopyCertificateFile(runspace, filePath, destinationPath); + + if (!errors.Any()) + { + errors = ImportCertificate(runspace, hostName, password, string.Format("c:\\{0}.pfx", guid), x509Cert.Thumbprint); + } + + DeleteCertificateFile(destinationPath, runspace); + + if (errors.Any()) + { + Log.WriteWarning(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray())); + throw new Exception(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray())); + } + } + + if (File.Exists(filePath)) + { + File.Delete(filePath); + } } finally { CloseRunspace(runspace); } } - - private string CopyCertificateFile(byte[] certificate, string hostName, Runspace runspace) - { - var destinationPath = string.Format("\\{0}\\c$\\remoteCert.pfx", hostName); - return destinationPath; + private object[] ImportCertificate(Runspace runspace, string hostName, string password, string certificatePath, string thumbprint) + { + var scripts = new List + { + string.Format("$mypwd = ConvertTo-SecureString -String {0} -Force –AsPlainText", password), + string.Format("Import-PfxCertificate –FilePath \"{0}\" cert:\\localMachine\\my -Password $mypwd", certificatePath), + string.Format("$cert = Get-Item cert:\\LocalMachine\\My\\{0}", thumbprint), + string.Format("$path = (Get-WmiObject -class \"Win32_TSGeneralSetting\" -Namespace root\\cimv2\\terminalservices -Filter \"TerminalName='RDP-tcp'\").__path"), + string.Format("Set-WmiInstance -Path $path -argument @{0}", string.Format("{{SSLCertificateSHA1Hash=\"{0}\"}}", thumbprint)) + }; + + object[] errors = null; + ExecuteRemoteShellCommand(runspace, hostName, scripts, out errors); + + return errors; } - private void DeleteCertificate(string path, Runspace runspace) + private string SaveCertificate(byte[] certificate, Guid guid) { + var filePath = string.Format("{0}{1}.pfx", Path.GetTempPath(), guid); + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + + File.WriteAllBytes(filePath, certificate); + + return filePath; + } + + private object[] CopyCertificateFile(Runspace runspace, string filePath, string destinationPath) + { + var scripts = new List + { + string.Format("Copy-Item \"{0}\" -Destination \"{1}\" -Force", filePath, destinationPath) + }; + + object[] errors = null; + ExecuteShellCommand(runspace, scripts, out errors); + + return errors; + } + + private object[] DeleteCertificateFile(string destinationPath, Runspace runspace) + { + var scripts = new List + { + string.Format("Remove-Item -Path \"{0}\" -Force", destinationPath) + }; + + object[] errors = null; + ExecuteShellCommand(runspace, scripts, out errors); + + return errors; } #endregion @@ -1242,7 +1322,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices } return users; - } + } private void AddUserGroupsToCollection(Runspace runSpace, string collectionName, List groups) { @@ -1257,7 +1337,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices private void AddComputerToCollectionAdComputerGroup(string organizationId, string collectionName, RdsServer server) { var computerPath = GetComputerPath(server.Name, false); - var computerGroupName = GetComputersGroupName( collectionName); + var computerGroupName = GetComputersGroupName( collectionName); if (!ActiveDirectoryUtils.AdObjectExists(computerPath)) { @@ -1273,6 +1353,11 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { ActiveDirectoryUtils.AddObjectToGroup(computerPath, GetComputerGroupPath(organizationId, collectionName)); } + + if (!ActiveDirectoryUtils.IsComputerInGroup(samName, RDSHelpDeskComputerGroup)) + { + ActiveDirectoryUtils.AddObjectToGroup(computerPath, GetHelpDeskComputerGroupPath()); + } } SetRDServerNewConnectionAllowed(false, server); @@ -1297,6 +1382,14 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { ActiveDirectoryUtils.RemoveObjectFromGroup(computerPath, GetComputerGroupPath(organizationId, collectionName)); } + + if (ActiveDirectoryUtils.AdObjectExists(GetHelpDeskComputerGroupPath())) + { + if (ActiveDirectoryUtils.IsComputerInGroup(samName, RDSHelpDeskComputerGroup)) + { + ActiveDirectoryUtils.RemoveObjectFromGroup(computerPath, GetHelpDeskComputerGroupPath()); + } + } } } @@ -1487,11 +1580,18 @@ namespace WebsitePanel.Providers.RemoteDesktopServices DisplayName = Convert.ToString(GetPSObjectProperty(psObject, "DisplayName")), FilePath = Convert.ToString(GetPSObjectProperty(psObject, "FilePath")), Alias = Convert.ToString(GetPSObjectProperty(psObject, "Alias")), - ShowInWebAccess = Convert.ToBoolean(GetPSObjectProperty(psObject, "ShowInWebAccess")) + ShowInWebAccess = Convert.ToBoolean(GetPSObjectProperty(psObject, "ShowInWebAccess")), + Users = null }; var requiredCommandLine = GetPSObjectProperty(psObject, "RequiredCommandLine"); remoteApp.RequiredCommandLine = requiredCommandLine == null ? null : requiredCommandLine.ToString(); + var users = (string[])(GetPSObjectProperty(psObject, "UserGroups")); + + if (users != null && users.Any()) + { + remoteApp.Users = users; + } return remoteApp; } @@ -1564,7 +1664,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices internal string GetComputerGroupPath(string organizationId, string collection) { StringBuilder sb = new StringBuilder(); - // append provider + AppendProtocol(sb); AppendDomainController(sb); AppendCNPath(sb, GetComputersGroupName(collection)); @@ -1573,12 +1673,25 @@ namespace WebsitePanel.Providers.RemoteDesktopServices AppendDomainPath(sb, RootDomain); return sb.ToString(); - } + } + + internal string GetHelpDeskComputerGroupPath() + { + StringBuilder sb = new StringBuilder(); + + AppendProtocol(sb); + AppendDomainController(sb); + AppendCNPath(sb, RDSHelpDeskComputerGroup); + AppendOUPath(sb, RootOU); + AppendDomainPath(sb, RootDomain); + + return sb.ToString(); + } internal string GetUsersGroupPath(string organizationId, string collection) { StringBuilder sb = new StringBuilder(); - // append provider + AppendProtocol(sb); AppendDomainController(sb); AppendCNPath(sb, GetUsersGroupName(collection)); diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs b/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs index b3bd520c..863d17ea 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs @@ -98,6 +98,8 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { private System.Threading.SendOrPostCallback RemoveRdsServerFromTenantOUOperationCompleted; + private System.Threading.SendOrPostCallback InstallCertificateOperationCompleted; + /// public RemoteDesktopServices() { this.Url = "http://localhost:9003/RemoteDesktopServices.asmx"; @@ -205,6 +207,9 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { /// public event RemoveRdsServerFromTenantOUCompletedEventHandler RemoveRdsServerFromTenantOUCompleted; + /// + public event InstallCertificateCompletedEventHandler InstallCertificateCompleted; + /// [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/server/CreateCollection", RequestNamespace="http://smbsaas/websitepanel/server/", ResponseNamespace="http://smbsaas/websitepanel/server/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] @@ -1675,6 +1680,52 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { } } + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/server/InstallCertificate", RequestNamespace="http://smbsaas/websitepanel/server/", ResponseNamespace="http://smbsaas/websitepanel/server/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public void InstallCertificate([System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary")] byte[] certificate, string password, string[] hostNames) { + this.Invoke("InstallCertificate", new object[] { + certificate, + password, + hostNames}); + } + + /// + public System.IAsyncResult BeginInstallCertificate(byte[] certificate, string password, string[] hostNames, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("InstallCertificate", new object[] { + certificate, + password, + hostNames}, callback, asyncState); + } + + /// + public void EndInstallCertificate(System.IAsyncResult asyncResult) { + this.EndInvoke(asyncResult); + } + + /// + public void InstallCertificateAsync(byte[] certificate, string password, string[] hostNames) { + this.InstallCertificateAsync(certificate, password, hostNames, null); + } + + /// + public void InstallCertificateAsync(byte[] certificate, string password, string[] hostNames, object userState) { + if ((this.InstallCertificateOperationCompleted == null)) { + this.InstallCertificateOperationCompleted = new System.Threading.SendOrPostCallback(this.OnInstallCertificateOperationCompleted); + } + this.InvokeAsync("InstallCertificate", new object[] { + certificate, + password, + hostNames}, this.InstallCertificateOperationCompleted, userState); + } + + private void OnInstallCertificateOperationCompleted(object arg) { + if ((this.InstallCertificateCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.InstallCertificateCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// public new void CancelAsync(object userState) { base.CancelAsync(userState); @@ -2300,4 +2351,8 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { /// [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] public delegate void RemoveRdsServerFromTenantOUCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void InstallCertificateCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); } diff --git a/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs b/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs index decdada6..03fec8aa 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs @@ -630,5 +630,21 @@ namespace WebsitePanel.Server throw; } } + + [WebMethod, SoapHeader("settings")] + public void InstallCertificate(byte[] certificate, string password, List hostNames) + { + try + { + Log.WriteStart("'{0}' InstallCertificate", ProviderSettings.ProviderName); + RDSProvider.InstallCertificate(certificate, password, hostNames); + Log.WriteEnd("'{0}' InstallCertificate", ProviderSettings.ProviderName); + } + catch (Exception ex) + { + Log.WriteError(String.Format("'{0}' InstallCertificate", ProviderSettings.ProviderName), ex); + throw; + } + } } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx index 03fcb7be..35afc963 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx @@ -5638,6 +5638,9 @@ Collection not created + + Session host certificate not installed + RDS Collection settings not updated diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionSettings.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionSettings.ascx.resx index 98985552..f20c77f4 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionSettings.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionSettings.ascx.resx @@ -129,6 +129,9 @@ Enable redirection for the following: + + Encryption Level + Idle session limit: @@ -141,6 +144,9 @@ Printers + + Security Layer + Set RD Session Host server timeout and reconnection settings for the session collection. @@ -153,6 +159,9 @@ Client Settings + + Security Settings + Session Settings diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.cs index 5d16a9ba..21ef3c4d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.cs @@ -63,7 +63,22 @@ namespace WebsitePanel.Portal.RDS } RdsCollection collection = new RdsCollection{ Name = txtCollectionName.Text, DisplayName = txtCollectionName.Text, Servers = servers.GetServers(), Description = "" }; - int collectionId = ES.Services.RDS.AddRdsCollection(PanelRequest.ItemID, collection); + int collectionId = ES.Services.RDS.AddRdsCollection(PanelRequest.ItemID, collection); + + try + { + if (upPFX.HasFile.Equals(true)) + { + byte[] pfx = upPFX.FileBytes; + string certPassword = txtPFXInstallPassword.Text; + //ES.Services.RDS.InstallSessionHostsCertificate(collectionId, pfx, certPassword); + } + } + catch(Exception ex) + { + messageBox.ShowErrorMessage("RDSSESSIONHOST_CERTIFICATE_NOT_INSTALLED", ex); + } + Response.Redirect(EditUrl("SpaceID", PanelSecurity.PackageId.ToString(), "rds_edit_collection", "CollectionId=" + collectionId, "ItemID=" + PanelRequest.ItemID)); } catch (Exception ex) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx index a2bd0546..56646324 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx @@ -175,6 +175,43 @@ + + + + +
+ + + + + + + + + + + + +
+ + + + + +
+ + + + + + +
+ +
+
+
+
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx.cs index b64a0df6..541ff80e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx.cs @@ -43,7 +43,10 @@ namespace WebsitePanel.Portal.RDS ClientPrinterRedirected = true, ClientPrinterAsDefault = true, RDEasyPrintDriverEnabled = true, - MaxRedirectedMonitors = 16 + MaxRedirectedMonitors = 16, + EncryptionLevel = EncryptionLevel.ClientCompatible.ToString(), + SecurityLayer = SecurityLayerValues.Negotiate.ToString(), + AuthenticateUsingNLA = true }; } @@ -89,6 +92,9 @@ namespace WebsitePanel.Portal.RDS chEasyPrint.Checked = collection.Settings.RDEasyPrintDriverEnabled; chEasyPrint.Enabled = collection.Settings.ClientPrinterRedirected; tbMonitorsNumber.Text = collection.Settings.MaxRedirectedMonitors.ToString(); + cbAuthentication.Checked = collection.Settings.AuthenticateUsingNLA; + ddSecurityLayer.SelectedValue = collection.Settings.SecurityLayer; + ddEncryptionLevel.SelectedValue = collection.Settings.EncryptionLevel; } private bool EditCollectionSettings() @@ -165,6 +171,9 @@ namespace WebsitePanel.Portal.RDS } settings.ClientDeviceRedirectionOptions = string.Join(",", redirectionOptions.ToArray()); + settings.AuthenticateUsingNLA = cbAuthentication.Checked; + settings.SecurityLayer = ddSecurityLayer.SelectedItem.Value; + settings.EncryptionLevel = ddEncryptionLevel.SelectedItem.Value; return settings; } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx.designer.cs index 0bb4e3f3..1d2b5bc2 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionSettings.ascx.designer.cs @@ -354,6 +354,69 @@ namespace WebsitePanel.Portal.RDS { /// protected global::System.Web.UI.WebControls.TextBox tbMonitorsNumber; + /// + /// secRdsSecuritySettings control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.CollapsiblePanel secRdsSecuritySettings; + + /// + /// panelRdsSecuritySettings control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Panel panelRdsSecuritySettings; + + /// + /// locSecurityLayer control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locSecurityLayer; + + /// + /// ddSecurityLayer control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.DropDownList ddSecurityLayer; + + /// + /// locEncryptionLevel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locEncryptionLevel; + + /// + /// ddEncryptionLevel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.DropDownList ddEncryptionLevel; + + /// + /// cbAuthentication control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox cbAuthentication; + /// /// buttonPanel control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx index 782d0213..94109cb6 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx @@ -1,4 +1,5 @@ <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="RDSCollectionApps.ascx.cs" Inherits="WebsitePanel.Portal.RDS.UserControls.RDSCollectionApps" %> +<%@ Import Namespace="WebsitePanel.Portal" %> <%@ Register Src="../../UserControls/PopupHeader.ascx" TagName="PopupHeader" TagPrefix="wsp" %> @@ -28,7 +29,13 @@ - + + + + + + +
From 96a9677e1907ff833e0219f6bdb566bf2af69baa Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Wed, 25 Feb 2015 20:54:59 -0500 Subject: [PATCH 02/21] Added tag build-2.1.0.593 for changeset 0d7afd9abf4e From 3b25027f741543ed948e7cedbbf2c329a303542d Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Wed, 25 Feb 2015 21:40:21 -0500 Subject: [PATCH 03/21] Change Naming of Local Administrators Groups for RDS --- .../Windows2012.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs index af65e3c0..8c90893d 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs @@ -67,11 +67,12 @@ namespace WebsitePanel.Providers.RemoteDesktopServices private const string RdsGroupFormat = "rds-{0}-{1}"; private const string RdsModuleName = "RemoteDesktopServices"; private const string AddNpsString = "netsh nps add np name=\"\"{0}\"\" policysource=\"1\" processingorder=\"{1}\" conditionid=\"0x3d\" conditiondata=\"^5$\" conditionid=\"0x1fb5\" conditiondata=\"{2}\" conditionid=\"0x1e\" conditiondata=\"UserAuthType:(PW|CA)\" profileid=\"0x1005\" profiledata=\"TRUE\" profileid=\"0x100f\" profiledata=\"TRUE\" profileid=\"0x1009\" profiledata=\"0x7\" profileid=\"0x1fe6\" profiledata=\"0x40000000\""; - private const string WspAdministratorsGroupName = "WSP-Administrators"; - private const string WspAdministratorsGroupDescription = "WSP Administrators"; + private const string WspAdministratorsGroupName = "WSP-Org-Administrators"; + private const string WspAdministratorsGroupDescription = "WSP Org Administrators"; private const string RdsServersOU = "RDSServers"; - private const string RDSHelpDeskComputerGroup = "Websitepanel-RDSHelpDesk-Computer"; - + private const string RDSHelpDeskGroup = "WSP-HelpDeskAdministrators"; + private const string RDSHelpDeskGroupDescription = "WSP Help Desk Administrators"; + #endregion #region Properties From c43df44c87a3eb02a52cfdea2eac93417efcf388 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Wed, 25 Feb 2015 21:48:12 -0500 Subject: [PATCH 04/21] Further Update Variable Name --- .../Windows2012.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs index 8c90893d..8c2db409 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs @@ -311,7 +311,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices if (!ActiveDirectoryUtils.AdObjectExists(GetHelpDeskComputerGroupPath())) { - ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskComputerGroup); + ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskGroup); } if (!ActiveDirectoryUtils.AdObjectExists(GetUsersGroupPath(organizationId, collection.Name))) @@ -568,7 +568,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices if (!ActiveDirectoryUtils.AdObjectExists(GetHelpDeskComputerGroupPath())) { - ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskComputerGroup); + ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskGroup); } AddComputerToCollectionAdComputerGroup(organizationId, collectionName, server); @@ -1355,7 +1355,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices ActiveDirectoryUtils.AddObjectToGroup(computerPath, GetComputerGroupPath(organizationId, collectionName)); } - if (!ActiveDirectoryUtils.IsComputerInGroup(samName, RDSHelpDeskComputerGroup)) + if (!ActiveDirectoryUtils.IsComputerInGroup(samName, RDSHelpDeskGroup)) { ActiveDirectoryUtils.AddObjectToGroup(computerPath, GetHelpDeskComputerGroupPath()); } @@ -1386,7 +1386,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices if (ActiveDirectoryUtils.AdObjectExists(GetHelpDeskComputerGroupPath())) { - if (ActiveDirectoryUtils.IsComputerInGroup(samName, RDSHelpDeskComputerGroup)) + if (ActiveDirectoryUtils.IsComputerInGroup(samName, RDSHelpDeskGroup)) { ActiveDirectoryUtils.RemoveObjectFromGroup(computerPath, GetHelpDeskComputerGroupPath()); } @@ -1682,7 +1682,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices AppendProtocol(sb); AppendDomainController(sb); - AppendCNPath(sb, RDSHelpDeskComputerGroup); + AppendCNPath(sb, RDSHelpDeskGroup); AppendOUPath(sb, RootOU); AppendDomainPath(sb, RootDomain); From 174b46b1d87469c7400a35b5b77601ec178013f2 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Wed, 25 Feb 2015 21:59:47 -0500 Subject: [PATCH 05/21] Added tag build-2.1.0.595 for changeset 448b3c1e561b From c4757f7d1dec66c4d5f5f19280366ea3986edb9d Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Thu, 26 Feb 2015 18:27:17 -0500 Subject: [PATCH 06/21] Added tag build-2.1.0.596 for changeset f5c5ecbcff98 From b3066aabfd43b6adcda68dbbe1d8bd83cce944df Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Thu, 26 Feb 2015 23:13:23 -0800 Subject: [PATCH 07/21] RDS HelpDesk Admins Group --- .../RemoteDesktopServicesController.cs | 4 +- .../IRemoteDesktopServices.cs | 2 +- .../Windows2012.cs | 104 +++++++++++++----- .../RemoteDesktopServicesProxy.cs | 19 ++-- .../RemoteDesktopServices.asmx.cs | 4 +- .../RDS/UserControls/RDSCollectionApps.ascx | 2 +- 6 files changed, 92 insertions(+), 43 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs index 91f589c3..c3bd42d7 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs @@ -663,8 +663,8 @@ namespace WebsitePanel.EnterpriseServer } var rds = GetRemoteDesktopServices(GetRemoteDesktopServiceID(org.PackageId)); - - rds.RemoveCollection(org.OrganizationId, collection.Name); + var servers = ObjectUtils.CreateListFromDataReader(DataProvider.GetRDSServersByCollectionId(collection.Id)).ToArray(); + rds.RemoveCollection(org.OrganizationId, collection.Name, servers); DataProvider.DeleteRDSCollection(collection.Id); } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs index 133eb575..a176c00f 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs @@ -43,7 +43,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices bool CreateCollection(string organizationId, RdsCollection collection); bool AddRdsServersToDeployment(RdsServer[] servers); RdsCollection GetCollection(string collectionName); - bool RemoveCollection(string organizationId, string collectionName); + bool RemoveCollection(string organizationId, string collectionName, List servers); bool SetUsersInCollection(string organizationId, string collectionName, List users); void AddSessionHostServerToCollection(string organizationId, string collectionName, RdsServer server); void AddSessionHostServersToCollection(string organizationId, string collectionName, List servers); diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs index af65e3c0..5e547dcb 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs @@ -71,6 +71,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices private const string WspAdministratorsGroupDescription = "WSP Administrators"; private const string RdsServersOU = "RDSServers"; private const string RDSHelpDeskComputerGroup = "Websitepanel-RDSHelpDesk-Computer"; + private const string RDSHelpDeskAdminsGroup = "WSP-HelpdeskAdmins"; #endregion @@ -308,10 +309,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices //ActiveDirectoryUtils.AddObjectToGroup(GetComputerPath(ConnectionBroker), GetComputerGroupPath(organizationId, collection.Name)); } - if (!ActiveDirectoryUtils.AdObjectExists(GetHelpDeskComputerGroupPath())) - { - ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskComputerGroup); - } + CheckOrCreateHelpDeskComputerGroup(); if (!ActiveDirectoryUtils.AdObjectExists(GetUsersGroupPath(organizationId, collection.Name))) { @@ -342,7 +340,13 @@ namespace WebsitePanel.Providers.RemoteDesktopServices //add session servers to group foreach (var rdsServer in collection.Servers) - { + { + if (!CheckLocalAdminsGroupExists(rdsServer.FqdName, runSpace)) + { + CreateLocalAdministratorsGroup(rdsServer.FqdName, runSpace); + } + + AddHelpDeskAdminsGroupToLocalAdmins(runSpace, rdsServer.FqdName); AddComputerToCollectionAdComputerGroup(organizationId, collection.Name, rdsServer); } } @@ -471,7 +475,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices return collection; } - public bool RemoveCollection(string organizationId, string collectionName) + public bool RemoveCollection(string organizationId, string collectionName, List servers) { var result = true; @@ -506,10 +510,13 @@ namespace WebsitePanel.Providers.RemoteDesktopServices RemoveNpsPolicy(runSpace, CentralNpsHost, capPolicyName); } - //Remove security group + foreach(var server in servers) + { + RemoveComputerFromCollectionAdComputerGroup(organizationId, collectionName, server); + } ActiveDirectoryUtils.DeleteADObject(GetComputerGroupPath(organizationId, collectionName)); - ActiveDirectoryUtils.DeleteADObject(GetUsersGroupPath(organizationId, collectionName)); + ActiveDirectoryUtils.DeleteADObject(GetUsersGroupPath(organizationId, collectionName)); } catch (Exception e) { @@ -565,11 +572,14 @@ namespace WebsitePanel.Providers.RemoteDesktopServices ExecuteShellCommand(runSpace, cmd, false); - if (!ActiveDirectoryUtils.AdObjectExists(GetHelpDeskComputerGroupPath())) + CheckOrCreateHelpDeskComputerGroup(); + + if (!CheckLocalAdminsGroupExists(server.FqdName, runSpace)) { - ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskComputerGroup); + CreateLocalAdministratorsGroup(server.FqdName, runSpace); } + AddHelpDeskAdminsGroupToLocalAdmins(runSpace, server.FqdName); AddComputerToCollectionAdComputerGroup(organizationId, collectionName, server); } catch (Exception e) @@ -969,7 +979,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices public void SaveRdsCollectionLocalAdmins(List users, List hosts) { - Runspace runspace = null; + Runspace runspace = null; try { @@ -994,7 +1004,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices throw new Exception(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray())); } } - + var existingAdmins = GetExistingLocalAdmins(hostName, runspace).Select(e => e.ToLower()); var formUsers = users.Select(u => string.Format("{0}\\{1}", domainName, u.SamAccountName).ToLower()); var newUsers = users.Where(u => !existingAdmins.Contains(string.Format("{0}\\{1}", domainName, u.SamAccountName).ToLower())); @@ -1009,6 +1019,8 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { RemoveLocalAdmin(hostName, user, runspace); } + + AddHelpDeskAdminsGroupToLocalAdmins(runspace, hostName); } } finally @@ -1141,6 +1153,53 @@ namespace WebsitePanel.Providers.RemoteDesktopServices #endregion + #region RDS Help Desk + + private string GetHelpDeskGroupPath(string groupName) + { + StringBuilder sb = new StringBuilder(); + + AppendProtocol(sb); + AppendDomainController(sb); + AppendCNPath(sb, groupName); + AppendOUPath(sb, RootOU); + AppendDomainPath(sb, RootDomain); + + return sb.ToString(); + } + + private void CheckOrCreateHelpDeskComputerGroup() + { + if (!ActiveDirectoryUtils.AdObjectExists(GetHelpDeskGroupPath(RDSHelpDeskComputerGroup))) + { + ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskComputerGroup); + } + } + + private void AddHelpDeskAdminsGroupToLocalAdmins(Runspace runspace, string hostName) + { + var helpDeskAdminsGroupPath = GetHelpDeskGroupPath(RDSHelpDeskAdminsGroup); + + if (!ActiveDirectoryUtils.AdObjectExists(helpDeskAdminsGroupPath)) + { + ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskAdminsGroup); + } + + var groupEntry = ActiveDirectoryUtils.GetADObject(helpDeskAdminsGroupPath); + var samAccountName = ActiveDirectoryUtils.GetADObjectProperty(groupEntry, "sAMAccountName"); + + var scripts = new List + { + string.Format("$GroupObj = [ADSI]\"WinNT://{0}/{1}\"", hostName, WspAdministratorsGroupName), + string.Format("$GroupObj.Add(\"WinNT://{0}/{1}\")", ServerSettings.ADRootDomain, samAccountName) + }; + + object[] errors = null; + ExecuteRemoteShellCommand(runspace, hostName, scripts, out errors); + } + + #endregion + #region SSL public void InstallCertificate(byte[] certificate, string password, List hostNames) @@ -1356,7 +1415,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices if (!ActiveDirectoryUtils.IsComputerInGroup(samName, RDSHelpDeskComputerGroup)) { - ActiveDirectoryUtils.AddObjectToGroup(computerPath, GetHelpDeskComputerGroupPath()); + ActiveDirectoryUtils.AddObjectToGroup(computerPath, GetHelpDeskGroupPath(RDSHelpDeskComputerGroup)); } } @@ -1383,11 +1442,11 @@ namespace WebsitePanel.Providers.RemoteDesktopServices ActiveDirectoryUtils.RemoveObjectFromGroup(computerPath, GetComputerGroupPath(organizationId, collectionName)); } - if (ActiveDirectoryUtils.AdObjectExists(GetHelpDeskComputerGroupPath())) + if (ActiveDirectoryUtils.AdObjectExists(GetHelpDeskGroupPath(RDSHelpDeskComputerGroup))) { if (ActiveDirectoryUtils.IsComputerInGroup(samName, RDSHelpDeskComputerGroup)) { - ActiveDirectoryUtils.RemoveObjectFromGroup(computerPath, GetHelpDeskComputerGroupPath()); + ActiveDirectoryUtils.RemoveObjectFromGroup(computerPath, GetHelpDeskGroupPath(RDSHelpDeskComputerGroup)); } } } @@ -1673,20 +1732,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices AppendDomainPath(sb, RootDomain); return sb.ToString(); - } - - internal string GetHelpDeskComputerGroupPath() - { - StringBuilder sb = new StringBuilder(); - - AppendProtocol(sb); - AppendDomainController(sb); - AppendCNPath(sb, RDSHelpDeskComputerGroup); - AppendOUPath(sb, RootOU); - AppendDomainPath(sb, RootDomain); - - return sb.ToString(); - } + } internal string GetUsersGroupPath(string organizationId, string collection) { diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs b/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs index 863d17ea..7d50298d 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs @@ -424,18 +424,20 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { /// [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/server/RemoveCollection", RequestNamespace="http://smbsaas/websitepanel/server/", ResponseNamespace="http://smbsaas/websitepanel/server/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public bool RemoveCollection(string organizationId, string collectionName) { + public bool RemoveCollection(string organizationId, string collectionName, RdsServer[] servers) { object[] results = this.Invoke("RemoveCollection", new object[] { organizationId, - collectionName}); + collectionName, + servers}); return ((bool)(results[0])); } /// - public System.IAsyncResult BeginRemoveCollection(string organizationId, string collectionName, System.AsyncCallback callback, object asyncState) { + public System.IAsyncResult BeginRemoveCollection(string organizationId, string collectionName, RdsServer[] servers, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("RemoveCollection", new object[] { organizationId, - collectionName}, callback, asyncState); + collectionName, + servers}, callback, asyncState); } /// @@ -445,18 +447,19 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { } /// - public void RemoveCollectionAsync(string organizationId, string collectionName) { - this.RemoveCollectionAsync(organizationId, collectionName, null); + public void RemoveCollectionAsync(string organizationId, string collectionName, RdsServer[] servers) { + this.RemoveCollectionAsync(organizationId, collectionName, servers, null); } /// - public void RemoveCollectionAsync(string organizationId, string collectionName, object userState) { + public void RemoveCollectionAsync(string organizationId, string collectionName, RdsServer[] servers, object userState) { if ((this.RemoveCollectionOperationCompleted == null)) { this.RemoveCollectionOperationCompleted = new System.Threading.SendOrPostCallback(this.OnRemoveCollectionOperationCompleted); } this.InvokeAsync("RemoveCollection", new object[] { organizationId, - collectionName}, this.RemoveCollectionOperationCompleted, userState); + collectionName, + servers}, this.RemoveCollectionOperationCompleted, userState); } private void OnRemoveCollectionOperationCompleted(object arg) { diff --git a/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs b/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs index 03fec8aa..038cc907 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs @@ -146,12 +146,12 @@ namespace WebsitePanel.Server } [WebMethod, SoapHeader("settings")] - public bool RemoveCollection(string organizationId, string collectionName) + public bool RemoveCollection(string organizationId, string collectionName, List servers) { try { Log.WriteStart("'{0}' RemoveCollection", ProviderSettings.ProviderName); - var result = RDSProvider.RemoveCollection(organizationId, collectionName); + var result = RDSProvider.RemoveCollection(organizationId, collectionName, servers); Log.WriteEnd("'{0}' RemoveCollection", ProviderSettings.ProviderName); return result; } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx index 94109cb6..02806956 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx @@ -33,7 +33,7 @@ - + From 789cd6ca11c069d1e7ebb6c8b75993c1bc1cbe21 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Fri, 27 Feb 2015 02:30:22 -0800 Subject: [PATCH 08/21] Small fixes --- .../Windows2012.cs | 30 +++++++++++++++---- .../WebsitePanel/RDS/RDSCollections.ascx | 4 +-- .../WebsitePanel/RDS/RDSCollections.ascx.cs | 4 +++ .../RDS/UserControls/RDSCollectionApps.ascx | 6 ++-- .../UserControls/RDSCollectionApps.ascx.cs | 8 +++++ 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs index 5e547dcb..dea195b8 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs @@ -67,11 +67,12 @@ namespace WebsitePanel.Providers.RemoteDesktopServices private const string RdsGroupFormat = "rds-{0}-{1}"; private const string RdsModuleName = "RemoteDesktopServices"; private const string AddNpsString = "netsh nps add np name=\"\"{0}\"\" policysource=\"1\" processingorder=\"{1}\" conditionid=\"0x3d\" conditiondata=\"^5$\" conditionid=\"0x1fb5\" conditiondata=\"{2}\" conditionid=\"0x1e\" conditiondata=\"UserAuthType:(PW|CA)\" profileid=\"0x1005\" profiledata=\"TRUE\" profileid=\"0x100f\" profiledata=\"TRUE\" profileid=\"0x1009\" profiledata=\"0x7\" profileid=\"0x1fe6\" profiledata=\"0x40000000\""; - private const string WspAdministratorsGroupName = "WSP-Administrators"; - private const string WspAdministratorsGroupDescription = "WSP Administrators"; + private const string WspAdministratorsGroupName = "WSP-Org-Administrators"; + private const string WspAdministratorsGroupDescription = "WSP Org Administrators"; private const string RdsServersOU = "RDSServers"; private const string RDSHelpDeskComputerGroup = "Websitepanel-RDSHelpDesk-Computer"; - private const string RDSHelpDeskAdminsGroup = "WSP-HelpdeskAdmins"; + private const string RDSHelpDeskGroup = "WSP-HelpDeskAdministrators"; + private const string RDSHelpDeskGroupDescription = "WSP Help Desk Administrators"; #endregion @@ -1178,14 +1179,31 @@ namespace WebsitePanel.Providers.RemoteDesktopServices private void AddHelpDeskAdminsGroupToLocalAdmins(Runspace runspace, string hostName) { - var helpDeskAdminsGroupPath = GetHelpDeskGroupPath(RDSHelpDeskAdminsGroup); + var helpDeskAdminsGroupPath = GetHelpDeskGroupPath(RDSHelpDeskGroup); + DirectoryEntry groupEntry = null; if (!ActiveDirectoryUtils.AdObjectExists(helpDeskAdminsGroupPath)) { - ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskAdminsGroup); + ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskGroup); + groupEntry = ActiveDirectoryUtils.GetADObject(helpDeskAdminsGroupPath); + + if (groupEntry.Properties.Contains("Description")) + { + groupEntry.Properties["Description"][0] = RDSHelpDeskGroupDescription; + } + else + { + groupEntry.Properties["Description"].Add(RDSHelpDeskGroupDescription); + } + + groupEntry.CommitChanges(); + } + + if (groupEntry == null) + { + groupEntry = ActiveDirectoryUtils.GetADObject(helpDeskAdminsGroupPath); } - var groupEntry = ActiveDirectoryUtils.GetADObject(helpDeskAdminsGroupPath); var samAccountName = ActiveDirectoryUtils.GetADObjectProperty(groupEntry, "sAMAccountName"); var scripts = new List diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx index 52e148f2..a311aaa3 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx @@ -47,8 +47,8 @@ - - <%# Eval("DisplayName").ToString() %> + + <%# Eval("DisplayName").ToString() %> diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx.cs index f7a57731..efdaaa56 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx.cs @@ -95,6 +95,10 @@ namespace WebsitePanel.Portal.RDS ShowErrorMessage("REMOTE_DESKTOP_SERVICES_REMOVE_COLLECTION", ex); } } + else if (e.CommandName == "EditCollection") + { + Response.Redirect(GetCollectionEditUrl(e.CommandArgument.ToString())); + } } protected void ddlPageSize_SelectedIndexChanged(object sender, EventArgs e) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx index 02806956..bbc141f1 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx @@ -9,7 +9,7 @@
@@ -24,8 +24,8 @@ - - + + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx.cs index 22651296..15bf0ecc 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx.cs @@ -254,6 +254,14 @@ namespace WebsitePanel.Portal.RDS.UserControls BindPopupApps(); } + protected void gvApps_RowCommand(object sender, GridViewCommandEventArgs e) + { + if (e.CommandName == "EditApplication") + { + Response.Redirect(GetCollectionUsersEditUrl(e.CommandArgument.ToString())); + } + } + protected SortDirection Direction { get { return ViewState[DirectionString] == null ? SortDirection.Descending : (SortDirection)ViewState[DirectionString]; } From a1c0b624902194d6da5182f0864045d239ea6722 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Fri, 27 Feb 2015 06:47:53 -0800 Subject: [PATCH 09/21] RDS Qoutas fixes --- WebsitePanel/Database/update_db.sql | 18 +++++++- .../RemoteDesktopServicesController.cs | 15 +++++- .../RemoteDesktopServices/RdsUserSession.cs | 2 + .../Windows2012.cs | 20 ++++---- .../AssignedRDSServers.ascx.resx | 2 +- .../RDSCollections.ascx.resx | 3 ++ .../RDSEditCollectionUsers.ascx.resx | 3 ++ .../WebsitePanel/RDS/AssignedRDSServers.ascx | 5 ++ .../RDS/AssignedRDSServers.ascx.cs | 20 ++++++-- .../RDS/AssignedRDSServers.ascx.designer.cs | 46 ++++++++----------- .../WebsitePanel/RDS/RDSCollections.ascx | 5 ++ .../WebsitePanel/RDS/RDSCollections.ascx.cs | 19 +++++++- .../RDS/RDSCollections.ascx.designer.cs | 18 ++++++++ .../RDS/RDSEditCollectionUsers.ascx | 6 +++ .../RDS/RDSEditCollectionUsers.ascx.cs | 18 +++++++- .../RDSEditCollectionUsers.ascx.designer.cs | 18 ++++++++ .../WebsitePanel/RDS/RDSUserSessions.ascx | 3 +- .../WebsitePanel/RDS/RDSUserSessions.ascx.cs | 12 +++++ 18 files changed, 187 insertions(+), 46 deletions(-) diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index 54df0493..27d8a6f9 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -6042,7 +6042,7 @@ CREATE PROCEDURE [dbo].GetOrganizationRdsUsersCount ) AS SELECT - @TotalNumber = Count([RDSCollectionId]) + @TotalNumber = Count(DISTINCT([AccountId])) FROM [dbo].[RDSCollectionUsers] WHERE [RDSCollectionId] in (SELECT [ID] FROM [RDSCollections] where [ItemId] = @ItemId ) RETURN @@ -8192,6 +8192,22 @@ AS INNER JOIN ServiceItems si ON ea.ItemID = si.ItemID INNER JOIN PackagesTreeCache pt ON si.PackageID = pt.PackageID WHERE pt.ParentPackageID = @PackageID AND ea.AccountType = 11) + ELSE IF @QuotaID = 450 + SET @Result = (SELECT COUNT(DISTINCT(RCU.[AccountId])) FROM [dbo].[RDSCollectionUsers] RCU + INNER JOIN ExchangeAccounts EA ON EA.AccountId = RCU.AccountId + INNER JOIN ServiceItems si ON ea.ItemID = si.ItemID + INNER JOIN PackagesTreeCache pt ON si.PackageID = pt.PackageID + WHERE PT.ParentPackageID = @PackageID) + ELSE IF @QuotaID = 451 + SET @Result = (SELECT COUNT(RS.[ID]) FROM [dbo].[RDSServers] RS + INNER JOIN ServiceItems si ON RS.ItemID = si.ItemID + INNER JOIN PackagesTreeCache pt ON si.PackageID = pt.PackageID + WHERE PT.ParentPackageID = @PackageID) + ELSE IF @QuotaID = 491 + SET @Result = (SELECT COUNT(RC.[ID]) FROM [dbo].[RDSCollections] RC + INNER JOIN ServiceItems si ON RC.ItemID = si.ItemID + INNER JOIN PackagesTreeCache pt ON si.PackageID = pt.PackageID + WHERE PT.ParentPackageID = @PackageID) ELSE IF @QuotaName like 'ServiceLevel.%' -- Support Service Level Quota BEGIN DECLARE @LevelID int diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs index c3bd42d7..269add07 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs @@ -760,8 +760,21 @@ namespace WebsitePanel.EnterpriseServer } var rds = GetRemoteDesktopServices(GetRemoteDesktopServiceID(organization.PackageId)); + var userSessions = rds.GetRdsUserSessions(collection.Name).ToList(); + var organizationUsers = OrganizationController.GetOrganizationUsersPaged(collection.ItemId, null, null, null, 0, Int32.MaxValue).PageUsers; - return rds.GetRdsUserSessions(collection.Name).ToList(); + foreach(var userSession in userSessions) + { + var organizationUser = organizationUsers.FirstOrDefault(o => o.SamAccountName.Equals(userSession.SamAccountName, StringComparison.CurrentCultureIgnoreCase)); + + if (organizationUser != null) + { + userSession.IsVip = organizationUser.IsVIP; + result.Add(userSession); + } + } + + return result; } private static RdsServersPaged GetFreeRdsServersPagedInternal(int itemId, string filterColumn, string filterValue, string sortColumn, int startRow, int maximumRows) diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsUserSession.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsUserSession.cs index 8c3e9729..4d6b4e19 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsUserSession.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsUserSession.cs @@ -13,5 +13,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices public string SessionState { get; set; } public string HostServer { get; set; } public string DomainName { get; set; } + public bool IsVip { get; set; } + public string SamAccountName { get; set; } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs index dea195b8..a0015101 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs @@ -2290,18 +2290,22 @@ namespace WebsitePanel.Providers.RemoteDesktopServices cmd.Parameters.Add("CollectionName", collectionName); cmd.Parameters.Add("ConnectionBroker", ConnectionBroker); var userSessions = ExecuteShellCommand(runSpace, cmd, false, out errors); - var properties = typeof(RdsUserSession).GetProperties(); + var properties = typeof(RdsUserSession).GetProperties(); foreach(var userSession in userSessions) { - var session = new RdsUserSession(); - - foreach(var prop in properties) + var session = new RdsUserSession { - prop.SetValue(session, GetPSObjectProperty(userSession, prop.Name).ToString(), null); - } - - session.UserName = GetUserFullName(session.DomainName, session.UserName, runSpace); + CollectionName = GetPSObjectProperty(userSession, "CollectionName").ToString(), + DomainName = GetPSObjectProperty(userSession, "DomainName").ToString(), + HostServer = GetPSObjectProperty(userSession, "HostServer").ToString(), + SessionState = GetPSObjectProperty(userSession, "SessionState").ToString(), + UnifiedSessionId = GetPSObjectProperty(userSession, "UnifiedSessionId").ToString(), + SamAccountName = GetPSObjectProperty(userSession, "UserName").ToString(), + }; + + session.IsVip = false; + session.UserName = GetUserFullName(session.DomainName, session.SamAccountName, runSpace); result.Add(session); } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/AssignedRDSServers.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/AssignedRDSServers.ascx.resx index 33277c17..e2d6204d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/AssignedRDSServers.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/AssignedRDSServers.ascx.resx @@ -145,7 +145,7 @@ Assigned RDS Servers - Total RDS Servers Allocated: + Total Remote Desktop Servers Allocated: Disable diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSCollections.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSCollections.ascx.resx index b231aa48..3a2deaac 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSCollections.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSCollections.ascx.resx @@ -147,4 +147,7 @@ RDS Server + + Total Remote Desktop Collections Created: + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionUsers.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionUsers.ascx.resx index b7086125..60f1cf4b 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionUsers.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionUsers.ascx.resx @@ -144,4 +144,7 @@ RDS Users + + Total RDS Users Assigned: + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/AssignedRDSServers.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/AssignedRDSServers.ascx index 6016913e..9ff6017f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/AssignedRDSServers.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/AssignedRDSServers.ascx @@ -72,6 +72,11 @@ +
+ +     + +
// This code was generated by a tool. @@ -139,6 +111,24 @@ namespace WebsitePanel.Portal.RDS { ///
protected global::System.Web.UI.WebControls.GridView gvRDSAssignedServers; + /// + /// locQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locQuota; + + /// + /// rdsServersQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.QuotaViewer rdsServersQuota; + /// /// odsRDSAssignedServersPaged control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx index a311aaa3..a5369d97 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx @@ -66,6 +66,11 @@ +
+ +     + +
protected global::System.Web.UI.WebControls.GridView gvRDSCollections; + /// + /// locQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locQuota; + + /// + /// collectionsQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.QuotaViewer collectionsQuota; + /// /// odsRDSCollectionsPaged control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx index 7f71695d..57a37195 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx @@ -1,6 +1,7 @@ <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="RDSEditCollectionUsers.ascx.cs" Inherits="WebsitePanel.Portal.RDS.RDSEditCollectionUsers" %> <%@ Register Src="../UserControls/SimpleMessageBox.ascx" TagName="SimpleMessageBox" TagPrefix="wsp" %> <%@ Register Src="../UserControls/EnableAsyncTasksSupport.ascx" TagName="EnableAsyncTasksSupport" TagPrefix="wsp" %> +<%@ Register Src="../UserControls/QuotaViewer.ascx" TagName="QuotaViewer" TagPrefix="wsp" %> <%@ Register Src="UserControls/RDSCollectionUsers.ascx" TagName="CollectionUsers" TagPrefix="wsp"%> <%@ Register Src="UserControls/RDSCollectionTabs.ascx" TagName="CollectionTabs" TagPrefix="wsp" %> <%@ Register TagPrefix="wsp" TagName="CollapsiblePanel" Src="../UserControls/CollapsiblePanel.ascx" %> @@ -34,6 +35,11 @@ +
+ +     + +
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.cs index beaeed58..767eab4f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.cs @@ -39,9 +39,10 @@ namespace WebsitePanel.Portal.RDS { protected void Page_Load(object sender, EventArgs e) - { + { if (!IsPostBack) { + BindQuota(); var collectionUsers = ES.Services.RDS.GetRdsCollectionUsers(PanelRequest.CollectionID); var collection = ES.Services.RDS.GetRdsCollection(PanelRequest.CollectionID); @@ -50,6 +51,20 @@ namespace WebsitePanel.Portal.RDS } } + private void BindQuota() + { + PackageContext cntx = PackagesHelper.GetCachedPackageContext(PanelSecurity.PackageId); + OrganizationStatistics stats = ES.Services.Organizations.GetOrganizationStatisticsByOrganization(PanelRequest.ItemID); + OrganizationStatistics tenantStats = ES.Services.Organizations.GetOrganizationStatistics(PanelRequest.ItemID); + usersQuota.QuotaUsedValue = stats.CreatedRdsUsers; + usersQuota.QuotaValue = stats.AllocatedRdsUsers; + + if (stats.AllocatedUsers != -1) + { + usersQuota.QuotaAvailable = tenantStats.AllocatedRdsUsers - tenantStats.CreatedRdsUsers; + } + } + private bool SaveRdsUsers() { try @@ -73,6 +88,7 @@ namespace WebsitePanel.Portal.RDS } SaveRdsUsers(); + BindQuota(); } protected void btnSaveExit_Click(object sender, EventArgs e) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.designer.cs index b4cdce32..e584e549 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.designer.cs @@ -93,6 +93,24 @@ namespace WebsitePanel.Portal.RDS { /// protected global::WebsitePanel.Portal.RDS.UserControls.RDSCollectionUsers users; + /// + /// locQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locQuota; + + /// + /// usersQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.QuotaViewer usersQuota; + /// /// buttonPanel control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx index 642ed06a..9afc8a5b 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx @@ -38,10 +38,11 @@ - + + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx.cs index 79e37ea8..9938e16e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx.cs @@ -5,6 +5,8 @@ using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; +using WebsitePanel.EnterpriseServer; +using WebsitePanel.Providers.HostedSolution; using WebsitePanel.Providers.RemoteDesktopServices; namespace WebsitePanel.Portal.RDS @@ -101,5 +103,15 @@ namespace WebsitePanel.Portal.RDS gvRDSUserSessions.DataSource = userSessions; gvRDSUserSessions.DataBind(); } + + public string GetAccountImage(bool vip) + { + if (vip) + { + return GetThemedImage("Exchange/vip_user_16.png"); + } + + return GetThemedImage("Exchange/accounting_mail_16.png"); + } } } \ No newline at end of file From 33e862d4a8811173dd5e67c271b344e1fa912869 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Fri, 27 Feb 2015 14:35:52 -0500 Subject: [PATCH 10/21] Added tag build-2.1.0.597 for changeset 976df1a41021 From d611121564dc514f121b523369beca2e7de2d14d Mon Sep 17 00:00:00 2001 From: Olov Karlsson Date: Sun, 1 Mar 2015 17:58:41 +0100 Subject: [PATCH 11/21] Fix for allowing all chars to be used when generating random password --- .../DesktopModules/WebsitePanel/Scripts/RandomPassword.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Scripts/RandomPassword.js b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Scripts/RandomPassword.js index f34f443f..57c95fa3 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Scripts/RandomPassword.js +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Scripts/RandomPassword.js @@ -65,7 +65,7 @@ function nchar(num) { function getRandomChars(_charsRange, _length, _target) { var _arr = []; var l1 = _charsRange[0]; - var rest = _charsRange[1] - _charsRange[0]; + var rest = _charsRange[1] - _charsRange[0] + 1; // while (_arr.length < _length) { var charCode = Math.floor(Math.random() * rest); From eb50917965715eb1a11017211fa1c583eae3a4bb Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Sun, 1 Mar 2015 12:15:45 -0500 Subject: [PATCH 12/21] Added tag build-2.1.0.598 for changeset ddb349e1b083 From e717a1578156faf991f49fb2409ec4e9e158500d Mon Sep 17 00:00:00 2001 From: me Date: Mon, 2 Mar 2015 13:55:12 +0400 Subject: [PATCH 13/21] fix typo for wsp-10317 Add enable\disable users ability for smart mail integration + multi-actions --- .../SmarterMail100_EditForwarding .ascx | 1 - .../SmarterMail100_EditForwarding.ascx | 1 + ... .ascx.cs => SmarterMail100_EditForwarding.ascx.cs} | 0 ... => SmarterMail100_EditForwarding.ascx.designer.cs} | 0 .../WebsitePanel/WebsitePanel.Portal.Modules.csproj | 10 +++++----- 5 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding .ascx create mode 100644 WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding.ascx rename WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/{SmarterMail100_EditForwarding .ascx.cs => SmarterMail100_EditForwarding.ascx.cs} (100%) rename WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/{SmarterMail100_EditForwarding .ascx.designer.cs => SmarterMail100_EditForwarding.ascx.designer.cs} (100%) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding .ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding .ascx deleted file mode 100644 index b54ae91c..00000000 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding .ascx +++ /dev/null @@ -1 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SmarterMail100_EditForwarding .ascx.cs" Inherits="WebsitePanel.Portal.ProviderControls.SmarterMail100_EditForwarding" %> diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding.ascx new file mode 100644 index 00000000..c882fc85 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding.ascx @@ -0,0 +1 @@ +<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SmarterMail100_EditForwarding.ascx.cs" Inherits="WebsitePanel.Portal.ProviderControls.SmarterMail100_EditForwarding" %> diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding .ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding.ascx.cs similarity index 100% rename from WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding .ascx.cs rename to WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding.ascx.cs diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding .ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding.ascx.designer.cs similarity index 100% rename from WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding .ascx.designer.cs rename to WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/SmarterMail100_EditForwarding.ascx.designer.cs diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj index e5fa35b0..c3f7651c 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj @@ -264,12 +264,12 @@ SmarterMail100_EditDomain_Throttling.ascx - - SmarterMail100_EditForwarding .ascx + + SmarterMail100_EditForwarding.ascx ASPXCodeBehind - - SmarterMail100_EditForwarding .ascx + + SmarterMail100_EditForwarding.ascx SmarterMail100_EditGroup.ascx @@ -4461,7 +4461,7 @@ - + From b51b6ee201edf7c62a60d4f3b6b3501d4ce1039c Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Mon, 2 Mar 2015 10:29:07 -0500 Subject: [PATCH 14/21] Added tag build-2.1.0.599 for changeset fe670172cd10 From ef3d4d2e5089bac193d918d2450dd65161061a9c Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Mon, 2 Mar 2015 12:20:48 -0500 Subject: [PATCH 15/21] Added tag build-2.1.0.600 for changeset e2e05db39b2b From 716855ae0551656dc29f6644a7168c6d8522ef21 Mon Sep 17 00:00:00 2001 From: dev_amdtel Date: Mon, 2 Mar 2015 23:44:26 +0400 Subject: [PATCH 16/21] fix import existing resources for old dns providers (including SimpleDNS) --- .../DnsServers/DnsServerController.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/DnsServers/DnsServerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/DnsServers/DnsServerController.cs index d659f9aa..bab622ac 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/DnsServers/DnsServerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/DnsServers/DnsServerController.cs @@ -32,6 +32,7 @@ using System.Collections.Specialized; using System.Globalization; using System.Linq; using System.Xml; +using System.Text; using System.Xml.Serialization; using WebsitePanel.Providers; using WebsitePanel.Providers.DNS; @@ -385,7 +386,9 @@ namespace WebsitePanel.EnterpriseServer var idn = new IdnMapping(); if (itemType == typeof(DnsZone)) - items.AddRange(dns.GetZones().Select(z => idn.GetUnicode(z))); + items.AddRange(dns.GetZones().Select(z => + Encoding.UTF8.GetByteCount(z) == z.Length ? // IsASCII + idn.GetUnicode(z) : z )); return items; } From 170cdc035827041909ea8f883cb4751084820558 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Mon, 2 Mar 2015 20:15:58 -0500 Subject: [PATCH 17/21] Remove Duplicate Handlers --- WebsitePanel/Sources/WebsitePanel.Server/Web.config | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.Server/Web.config b/WebsitePanel/Sources/WebsitePanel.Server/Web.config index d9d1bde5..0dcd0c7d 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/Web.config +++ b/WebsitePanel/Sources/WebsitePanel.Server/Web.config @@ -5,17 +5,6 @@
- - - -
-
-
-
- -
- - From d7af90326c21dc19eaa9d978f7c286f20b408d08 Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Mon, 2 Mar 2015 20:29:52 -0500 Subject: [PATCH 18/21] Added tag build-2.1.0.601 for changeset 8ccdc857fa3f From 6af59c8cc86a6dd4da0efa6a2a8d015ca639975b Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Mon, 2 Mar 2015 22:48:46 -0500 Subject: [PATCH 19/21] Added tag build-2.1.0.602 for changeset 28e4e60c0e5c From 1969cd398c584f44fca41e362b45818965b09916 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Tue, 3 Mar 2015 07:43:23 -0800 Subject: [PATCH 20/21] Session Host certificates --- WebsitePanel/Database/update_db.sql | 95 +++++++- .../RemoteDesktopServicesProxy.cs | 166 +++++++++++-- .../Data/DataProvider.cs | 31 +++ .../RemoteDesktopServicesController.cs | 96 +++++++- .../esRemoteDesktopServices.asmx.cs | 16 +- .../IRemoteDesktopServices.cs | 4 +- .../RemoteDesktopServices/RdsCertificate.cs | 18 ++ .../RemoteDesktopServices/RdsUserSession.cs | 2 + .../WebsitePanel.Providers.Base.csproj | 1 + .../Windows2012.cs | 229 +++++++----------- .../RemoteDesktopServicesProxy.cs | 42 ++-- .../RemoteDesktopServices.asmx.cs | 8 +- .../WebsitePanel_SharedResources.ascx.resx | 3 + .../App_LocalResources/RDSServers.ascx.resx | 3 + .../WebsitePanel/Code/Helpers/RDSHelper.cs | 14 +- .../App_LocalResources/RDS_Settings.ascx.resx | 3 + .../ProviderControls/RDS_Settings.ascx | 14 +- .../ProviderControls/RDS_Settings.ascx.cs | 25 +- .../RDS_Settings.ascx.designer.cs | 46 ++-- .../AssignedRDSServers.ascx.resx | 2 +- .../RDSCollections.ascx.resx | 3 + .../RDSEditApplicationUsers.ascx.resx | 6 + .../RDSEditCollectionUsers.ascx.resx | 3 + .../WebsitePanel/RDS/AssignedRDSServers.ascx | 5 + .../RDS/AssignedRDSServers.ascx.cs | 20 +- .../RDS/AssignedRDSServers.ascx.designer.cs | 46 ++-- .../WebsitePanel/RDS/RDSCollections.ascx | 5 + .../WebsitePanel/RDS/RDSCollections.ascx.cs | 19 +- .../RDS/RDSCollections.ascx.designer.cs | 18 ++ .../WebsitePanel/RDS/RDSCreateCollection.ascx | 22 +- .../RDS/RDSCreateCollection.ascx.cs | 16 +- .../RDS/RDSCreateCollection.ascx.designer.cs | 36 --- .../RDS/RDSEditApplicationUsers.ascx | 8 +- .../RDS/RDSEditApplicationUsers.ascx.cs | 5 + .../RDSEditApplicationUsers.ascx.designer.cs | 22 +- .../RDS/RDSEditCollectionUsers.ascx | 6 + .../RDS/RDSEditCollectionUsers.ascx.cs | 18 +- .../RDSEditCollectionUsers.ascx.designer.cs | 18 ++ .../WebsitePanel/RDS/RDSUserSessions.ascx | 3 +- .../WebsitePanel/RDS/RDSUserSessions.ascx.cs | 12 + .../UserControls/RDSCollectionApps.ascx.cs | 2 +- .../WebsitePanel/RDSServers.ascx | 156 +++++++++++- .../WebsitePanel/RDSServers.ascx.cs | 81 ++++++- .../WebsitePanel/RDSServers.ascx.designer.cs | 221 ++++++++++++++--- .../WebsitePanel.Portal.Modules.csproj | 4 +- 45 files changed, 1196 insertions(+), 377 deletions(-) create mode 100644 WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsCertificate.cs diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index 54df0493..cbe31226 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -5508,6 +5508,23 @@ CREATE TABLE [dbo].[RDSCollectionSettings]( GO +IF NOT EXISTS(SELECT * FROM SYS.TABLES WHERE name = 'RDSCertificates') +CREATE TABLE [dbo].[RDSCertificates]( + [ID] [int] IDENTITY(1,1) NOT NULL, + [ServiceId] [int] NOT NULL, + [Content] [ntext] NOT NULL, + [Hash] [nvarchar](255) NOT NULL, + [FileName] [nvarchar](255) NOT NULL, + [ValidFrom] [datetime] NULL, + [ExpiryDate] [datetime] NULL + CONSTRAINT [PK_RDSCertificates] PRIMARY KEY CLUSTERED +( + [ID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + +GO + ALTER TABLE [dbo].[RDSCollectionUsers] DROP CONSTRAINT [FK_RDSCollectionUsers_RDSCollectionId] @@ -5548,6 +5565,66 @@ GO /*Remote Desktop Services Procedures*/ +IF EXISTS (SELECT * FROM SYS.OBJECTS WHERE type = 'P' AND name = 'AddRDSCertificate') +DROP PROCEDURE AddRDSCertificate +GO +CREATE PROCEDURE [dbo].[AddRDSCertificate] +( + @RDSCertificateId INT OUTPUT, + @ServiceId INT, + @Content NTEXT, + @Hash NVARCHAR(255), + @FileName NVARCHAR(255), + @ValidFrom DATETIME, + @ExpiryDate DATETIME +) +AS +INSERT INTO RDSCertificates +( + ServiceId, + Content, + Hash, + FileName, + ValidFrom, + ExpiryDate +) +VALUES +( + @ServiceId, + @Content, + @Hash, + @FileName, + @ValidFrom, + @ExpiryDate +) + +SET @RDSCertificateId = SCOPE_IDENTITY() + +RETURN +GO + + +IF EXISTS (SELECT * FROM SYS.OBJECTS WHERE type = 'P' AND name = 'GetRDSCertificateByServiceId') +DROP PROCEDURE GetRDSCertificateByServiceId +GO +CREATE PROCEDURE [dbo].[GetRDSCertificateByServiceId] +( + @ServiceId INT +) +AS +SELECT TOP 1 + Id, + ServiceId, + Content, + Hash, + FileName, + ValidFrom, + ExpiryDate + FROM RDSCertificates + WHERE ServiceId = @ServiceId + ORDER BY Id DESC +GO + IF EXISTS (SELECT * FROM SYS.OBJECTS WHERE type = 'P' AND name = 'AddRDSServer') DROP PROCEDURE AddRDSServer GO @@ -6042,7 +6119,7 @@ CREATE PROCEDURE [dbo].GetOrganizationRdsUsersCount ) AS SELECT - @TotalNumber = Count([RDSCollectionId]) + @TotalNumber = Count(DISTINCT([AccountId])) FROM [dbo].[RDSCollectionUsers] WHERE [RDSCollectionId] in (SELECT [ID] FROM [RDSCollections] where [ItemId] = @ItemId ) RETURN @@ -8192,6 +8269,22 @@ AS INNER JOIN ServiceItems si ON ea.ItemID = si.ItemID INNER JOIN PackagesTreeCache pt ON si.PackageID = pt.PackageID WHERE pt.ParentPackageID = @PackageID AND ea.AccountType = 11) + ELSE IF @QuotaID = 450 + SET @Result = (SELECT COUNT(DISTINCT(RCU.[AccountId])) FROM [dbo].[RDSCollectionUsers] RCU + INNER JOIN ExchangeAccounts EA ON EA.AccountId = RCU.AccountId + INNER JOIN ServiceItems si ON ea.ItemID = si.ItemID + INNER JOIN PackagesTreeCache pt ON si.PackageID = pt.PackageID + WHERE PT.ParentPackageID = @PackageID) + ELSE IF @QuotaID = 451 + SET @Result = (SELECT COUNT(RS.[ID]) FROM [dbo].[RDSServers] RS + INNER JOIN ServiceItems si ON RS.ItemID = si.ItemID + INNER JOIN PackagesTreeCache pt ON si.PackageID = pt.PackageID + WHERE PT.ParentPackageID = @PackageID) + ELSE IF @QuotaID = 491 + SET @Result = (SELECT COUNT(RC.[ID]) FROM [dbo].[RDSCollections] RC + INNER JOIN ServiceItems si ON RC.ItemID = si.ItemID + INNER JOIN PackagesTreeCache pt ON si.PackageID = pt.PackageID + WHERE PT.ParentPackageID = @PackageID) ELSE IF @QuotaName like 'ServiceLevel.%' -- Support Service Level Quota BEGIN DECLARE @LevelID int diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/RemoteDesktopServicesProxy.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/RemoteDesktopServicesProxy.cs index 3214d80d..c5fba734 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/RemoteDesktopServicesProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/RemoteDesktopServicesProxy.cs @@ -120,6 +120,10 @@ namespace WebsitePanel.EnterpriseServer { private System.Threading.SendOrPostCallback InstallSessionHostsCertificateOperationCompleted; + private System.Threading.SendOrPostCallback GetRdsCertificateByServiceIdOperationCompleted; + + private System.Threading.SendOrPostCallback AddRdsCertificateOperationCompleted; + /// public esRemoteDesktopServices() { this.Url = "http://localhost:9002/esRemoteDesktopServices.asmx"; @@ -260,6 +264,12 @@ namespace WebsitePanel.EnterpriseServer { /// public event InstallSessionHostsCertificateCompletedEventHandler InstallSessionHostsCertificateCompleted; + /// + public event GetRdsCertificateByServiceIdCompletedEventHandler GetRdsCertificateByServiceIdCompleted; + + /// + public event AddRdsCertificateCompletedEventHandler AddRdsCertificateCompleted; + /// [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/GetRdsCollection", RequestNamespace="http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace="http://smbsaas/websitepanel/enterpriseserver", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public RdsCollection GetRdsCollection(int collectionId) { @@ -2245,20 +2255,16 @@ namespace WebsitePanel.EnterpriseServer { /// [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/InstallSessionHostsCertificate", RequestNamespace="http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace="http://smbsaas/websitepanel/enterpriseserver", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public ResultObject InstallSessionHostsCertificate(int collectionId, [System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary")] byte[] certificate, string password) { + public ResultObject InstallSessionHostsCertificate(RdsServer rdsServer) { object[] results = this.Invoke("InstallSessionHostsCertificate", new object[] { - collectionId, - certificate, - password}); + rdsServer}); return ((ResultObject)(results[0])); } /// - public System.IAsyncResult BeginInstallSessionHostsCertificate(int collectionId, byte[] certificate, string password, System.AsyncCallback callback, object asyncState) { + public System.IAsyncResult BeginInstallSessionHostsCertificate(RdsServer rdsServer, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("InstallSessionHostsCertificate", new object[] { - collectionId, - certificate, - password}, callback, asyncState); + rdsServer}, callback, asyncState); } /// @@ -2268,19 +2274,17 @@ namespace WebsitePanel.EnterpriseServer { } /// - public void InstallSessionHostsCertificateAsync(int collectionId, byte[] certificate, string password) { - this.InstallSessionHostsCertificateAsync(collectionId, certificate, password, null); + public void InstallSessionHostsCertificateAsync(RdsServer rdsServer) { + this.InstallSessionHostsCertificateAsync(rdsServer, null); } /// - public void InstallSessionHostsCertificateAsync(int collectionId, byte[] certificate, string password, object userState) { + public void InstallSessionHostsCertificateAsync(RdsServer rdsServer, object userState) { if ((this.InstallSessionHostsCertificateOperationCompleted == null)) { this.InstallSessionHostsCertificateOperationCompleted = new System.Threading.SendOrPostCallback(this.OnInstallSessionHostsCertificateOperationCompleted); } this.InvokeAsync("InstallSessionHostsCertificate", new object[] { - collectionId, - certificate, - password}, this.InstallSessionHostsCertificateOperationCompleted, userState); + rdsServer}, this.InstallSessionHostsCertificateOperationCompleted, userState); } private void OnInstallSessionHostsCertificateOperationCompleted(object arg) { @@ -2290,6 +2294,88 @@ namespace WebsitePanel.EnterpriseServer { } } + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/GetRdsCertificateByServiceId", RequestNamespace="http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace="http://smbsaas/websitepanel/enterpriseserver", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public RdsCertificate GetRdsCertificateByServiceId(int serviceId) { + object[] results = this.Invoke("GetRdsCertificateByServiceId", new object[] { + serviceId}); + return ((RdsCertificate)(results[0])); + } + + /// + public System.IAsyncResult BeginGetRdsCertificateByServiceId(int serviceId, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("GetRdsCertificateByServiceId", new object[] { + serviceId}, callback, asyncState); + } + + /// + public RdsCertificate EndGetRdsCertificateByServiceId(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((RdsCertificate)(results[0])); + } + + /// + public void GetRdsCertificateByServiceIdAsync(int serviceId) { + this.GetRdsCertificateByServiceIdAsync(serviceId, null); + } + + /// + public void GetRdsCertificateByServiceIdAsync(int serviceId, object userState) { + if ((this.GetRdsCertificateByServiceIdOperationCompleted == null)) { + this.GetRdsCertificateByServiceIdOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetRdsCertificateByServiceIdOperationCompleted); + } + this.InvokeAsync("GetRdsCertificateByServiceId", new object[] { + serviceId}, this.GetRdsCertificateByServiceIdOperationCompleted, userState); + } + + private void OnGetRdsCertificateByServiceIdOperationCompleted(object arg) { + if ((this.GetRdsCertificateByServiceIdCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.GetRdsCertificateByServiceIdCompleted(this, new GetRdsCertificateByServiceIdCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/AddRdsCertificate", RequestNamespace="http://smbsaas/websitepanel/enterpriseserver", ResponseNamespace="http://smbsaas/websitepanel/enterpriseserver", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public ResultObject AddRdsCertificate(RdsCertificate certificate) { + object[] results = this.Invoke("AddRdsCertificate", new object[] { + certificate}); + return ((ResultObject)(results[0])); + } + + /// + public System.IAsyncResult BeginAddRdsCertificate(RdsCertificate certificate, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("AddRdsCertificate", new object[] { + certificate}, callback, asyncState); + } + + /// + public ResultObject EndAddRdsCertificate(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((ResultObject)(results[0])); + } + + /// + public void AddRdsCertificateAsync(RdsCertificate certificate) { + this.AddRdsCertificateAsync(certificate, null); + } + + /// + public void AddRdsCertificateAsync(RdsCertificate certificate, object userState) { + if ((this.AddRdsCertificateOperationCompleted == null)) { + this.AddRdsCertificateOperationCompleted = new System.Threading.SendOrPostCallback(this.OnAddRdsCertificateOperationCompleted); + } + this.InvokeAsync("AddRdsCertificate", new object[] { + certificate}, this.AddRdsCertificateOperationCompleted, userState); + } + + private void OnAddRdsCertificateOperationCompleted(object arg) { + if ((this.AddRdsCertificateCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.AddRdsCertificateCompleted(this, new AddRdsCertificateCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// public new void CancelAsync(object userState) { base.CancelAsync(userState); @@ -3465,4 +3551,56 @@ namespace WebsitePanel.EnterpriseServer { } } } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void GetRdsCertificateByServiceIdCompletedEventHandler(object sender, GetRdsCertificateByServiceIdCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class GetRdsCertificateByServiceIdCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal GetRdsCertificateByServiceIdCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public RdsCertificate Result { + get { + this.RaiseExceptionIfNecessary(); + return ((RdsCertificate)(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void AddRdsCertificateCompletedEventHandler(object sender, AddRdsCertificateCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class AddRdsCertificateCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal AddRdsCertificateCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public ResultObject Result { + get { + this.RaiseExceptionIfNecessary(); + return ((ResultObject)(this.results[0])); + } + } + } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Data/DataProvider.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Data/DataProvider.cs index 1d903a9c..0c75029f 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Data/DataProvider.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Data/DataProvider.cs @@ -4613,6 +4613,37 @@ namespace WebsitePanel.EnterpriseServer #region RDS + public static int AddRdsCertificate(int serviceId, string content, byte[] hash, string fileName, DateTime? validFrom, DateTime? expiryDate) + { + SqlParameter rdsCertificateId = new SqlParameter("@RDSCertificateID", SqlDbType.Int); + rdsCertificateId.Direction = ParameterDirection.Output; + + SqlHelper.ExecuteNonQuery( + ConnectionString, + CommandType.StoredProcedure, + "AddRDSCertificate", + rdsCertificateId, + new SqlParameter("@ServiceId", serviceId), + new SqlParameter("@Content", content), + new SqlParameter("@Hash", Convert.ToBase64String(hash)), + new SqlParameter("@FileName", fileName), + new SqlParameter("@ValidFrom", validFrom), + new SqlParameter("@ExpiryDate", expiryDate) + ); + + return Convert.ToInt32(rdsCertificateId.Value); + } + + public static IDataReader GetRdsCertificateByServiceId(int serviceId) + { + return SqlHelper.ExecuteReader( + ConnectionString, + CommandType.StoredProcedure, + "GetRDSCertificateByServiceId", + new SqlParameter("@ServiceId", serviceId) + ); + } + public static IDataReader GetRdsCollectionSettingsByCollectionId(int collectionId) { return SqlHelper.ExecuteReader( diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs index c3bd42d7..763e96aa 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/RemoteDesktopServices/RemoteDesktopServicesController.cs @@ -278,19 +278,28 @@ namespace WebsitePanel.EnterpriseServer return SaveRdsCollectionLocalAdminsInternal(users, collectionId); } - public static ResultObject InstallSessionHostsCertificate(int collectionId, byte[] certificate, string password) + public static ResultObject InstallSessionHostsCertificate(RdsServer rdsServer) { - return InstallSessionHostsCertificateInternal(collectionId, certificate, password); + return InstallSessionHostsCertificateInternal(rdsServer); } - private static ResultObject InstallSessionHostsCertificateInternal(int collectionId, byte[] certificate, string password) + public static RdsCertificate GetRdsCertificateByServiceId(int serviceId) + { + return GetRdsCertificateByServiceIdInternal(serviceId); + } + + public static ResultObject AddRdsCertificate(RdsCertificate certificate) + { + return AddRdsCertificateInternal(certificate); + } + + private static ResultObject InstallSessionHostsCertificateInternal(RdsServer rdsServer) { var result = TaskManager.StartResultTask("REMOTE_DESKTOP_SERVICES", "INSTALL_CERTIFICATE"); try - { - var collection = ObjectUtils.FillObjectFromDataReader(DataProvider.GetRDSCollectionById(collectionId)); - Organization org = OrganizationController.GetOrganization(collection.ItemId); + { + Organization org = OrganizationController.GetOrganization(rdsServer.ItemId.Value); if (org == null) { @@ -299,10 +308,17 @@ namespace WebsitePanel.EnterpriseServer return result; } - var rds = GetRemoteDesktopServices(GetRemoteDesktopServiceID(org.PackageId)); - var servers = ObjectUtils.CreateListFromDataReader(DataProvider.GetRDSServersByCollectionId(collection.Id)).ToList(); + int serviceId = GetRemoteDesktopServiceID(org.PackageId); + var rds = GetRemoteDesktopServices(serviceId); + var certificate = GetRdsCertificateByServiceIdInternal(serviceId); + + var array = Convert.FromBase64String(certificate.Hash); + char[] chars = new char[array.Length / sizeof(char)]; + System.Buffer.BlockCopy(array, 0, chars, 0, array.Length); + string password = new string(chars); + byte[] content = Convert.FromBase64String(certificate.Content); - rds.InstallCertificate(certificate, password, servers.Select(s => s.FqdName).ToArray()); + rds.InstallCertificate(content, password, new string[] {rdsServer.FqdName}); } catch (Exception ex) { @@ -323,6 +339,49 @@ namespace WebsitePanel.EnterpriseServer return result; } + private static RdsCertificate GetRdsCertificateByServiceIdInternal(int serviceId) + { + var result = ObjectUtils.FillObjectFromDataReader(DataProvider.GetRdsCertificateByServiceId(serviceId)); + + return result; + } + + private static ResultObject AddRdsCertificateInternal(RdsCertificate certificate) + { + var result = TaskManager.StartResultTask("REMOTE_DESKTOP_SERVICES", "ADD_RDS_SERVER"); + + try + { + byte[] hash = new byte[certificate.Hash.Length * sizeof(char)]; + System.Buffer.BlockCopy(certificate.Hash.ToCharArray(), 0, hash, 0, hash.Length); + certificate.Id = DataProvider.AddRdsCertificate(certificate.ServiceId, certificate.Content, hash, certificate.FileName, certificate.ValidFrom, certificate.ExpiryDate); + } + catch (Exception ex) + { + if (ex.InnerException != null) + { + result.AddError("Unable to add RDS Certificate", ex.InnerException); + } + else + { + result.AddError("Unable to add RDS Certificate", ex); + } + } + finally + { + if (!result.IsSuccess) + { + TaskManager.CompleteResultTask(result); + } + else + { + TaskManager.CompleteResultTask(); + } + } + + return result; + } + private static RdsCollection GetRdsCollectionInternal(int collectionId) { var collection = ObjectUtils.FillObjectFromDataReader(DataProvider.GetRDSCollectionById(collectionId)); @@ -370,7 +429,7 @@ namespace WebsitePanel.EnterpriseServer var rds = GetRemoteDesktopServices(GetRemoteDesktopServiceID(org.PackageId)); var organizationUsers = OrganizationController.GetOrganizationUsersPaged(collection.ItemId, null, null, null, 0, Int32.MaxValue).PageUsers; - var organizationAdmins = rds.GetRdsCollectionLocalAdmins(servers.First().FqdName); + var organizationAdmins = rds.GetRdsCollectionLocalAdmins(org.OrganizationId, collection.Name); return organizationUsers.Where(o => organizationAdmins.Select(a => a.ToLower()).Contains(o.DomainUserName.ToLower())).ToList(); } @@ -394,7 +453,7 @@ namespace WebsitePanel.EnterpriseServer var rds = GetRemoteDesktopServices(GetRemoteDesktopServiceID(org.PackageId)); var servers = ObjectUtils.CreateListFromDataReader(DataProvider.GetRDSServersByCollectionId(collection.Id)).ToList(); - rds.SaveRdsCollectionLocalAdmins(users, servers.Select(s => s.FqdName).ToArray()); + rds.SaveRdsCollectionLocalAdmins(users.Select(u => u.AccountName).ToArray(), servers.Select(s => s.FqdName).ToArray(), org.OrganizationId, collection.Name); } catch (Exception ex) { @@ -760,8 +819,21 @@ namespace WebsitePanel.EnterpriseServer } var rds = GetRemoteDesktopServices(GetRemoteDesktopServiceID(organization.PackageId)); + var userSessions = rds.GetRdsUserSessions(collection.Name).ToList(); + var organizationUsers = OrganizationController.GetOrganizationUsersPaged(collection.ItemId, null, null, null, 0, Int32.MaxValue).PageUsers; - return rds.GetRdsUserSessions(collection.Name).ToList(); + foreach(var userSession in userSessions) + { + var organizationUser = organizationUsers.FirstOrDefault(o => o.SamAccountName.Equals(userSession.SamAccountName, StringComparison.CurrentCultureIgnoreCase)); + + if (organizationUser != null) + { + userSession.IsVip = organizationUser.IsVIP; + result.Add(userSession); + } + } + + return result; } private static RdsServersPaged GetFreeRdsServersPagedInternal(int itemId, string filterColumn, string filterValue, string sortColumn, int startRow, int maximumRows) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esRemoteDesktopServices.asmx.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esRemoteDesktopServices.asmx.cs index 8cd3ecdb..f377ff8d 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esRemoteDesktopServices.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esRemoteDesktopServices.asmx.cs @@ -327,9 +327,21 @@ namespace WebsitePanel.EnterpriseServer } [WebMethod] - public ResultObject InstallSessionHostsCertificate(int collectionId, byte[] certificate, string password) + public ResultObject InstallSessionHostsCertificate(RdsServer rdsServer) { - return RemoteDesktopServicesController.InstallSessionHostsCertificate(collectionId, certificate, password); + return RemoteDesktopServicesController.InstallSessionHostsCertificate(rdsServer); + } + + [WebMethod] + public RdsCertificate GetRdsCertificateByServiceId(int serviceId) + { + return RemoteDesktopServicesController.GetRdsCertificateByServiceId(serviceId); + } + + [WebMethod] + public ResultObject AddRdsCertificate(RdsCertificate certificate) + { + return RemoteDesktopServicesController.AddRdsCertificate(certificate); } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs index a176c00f..695f2576 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/IRemoteDesktopServices.cs @@ -74,8 +74,8 @@ namespace WebsitePanel.Providers.RemoteDesktopServices string GetRdsServerStatus(string serverName); void ShutDownRdsServer(string serverName); void RestartRdsServer(string serverName); - void SaveRdsCollectionLocalAdmins(List users, List hosts); - List GetRdsCollectionLocalAdmins(string hostName); + void SaveRdsCollectionLocalAdmins(List users, List hosts, string collectionName, string organizationId); + List GetRdsCollectionLocalAdmins(string organizationId, string collectionName); void MoveRdsServerToTenantOU(string hostName, string organizationId); void RemoveRdsServerFromTenantOU(string hostName, string organizationId); void InstallCertificate(byte[] certificate, string password, List hostNames); diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsCertificate.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsCertificate.cs new file mode 100644 index 00000000..9d8e0e3e --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsCertificate.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace WebsitePanel.Providers.RemoteDesktopServices +{ + public class RdsCertificate + { + public int Id { get; set; } + public int ServiceId { get; set; } + public string FileName { get; set; } + public string Content { get; set; } + public string Hash { get; set; } + public DateTime? ValidFrom { get; set; } + public DateTime? ExpiryDate { get; set; } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsUserSession.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsUserSession.cs index 8c3e9729..4d6b4e19 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsUserSession.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/RemoteDesktopServices/RdsUserSession.cs @@ -13,5 +13,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices public string SessionState { get; set; } public string HostServer { get; set; } public string DomainName { get; set; } + public bool IsVip { get; set; } + public string SamAccountName { get; set; } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj index 752209d3..c0f01014 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj @@ -129,6 +129,7 @@ + diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs index dea195b8..ca1b4c3b 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.TerminalServices.Windows2012/Windows2012.cs @@ -64,6 +64,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices private const string Computers = "Computers"; private const string AdDcComputers = "Domain Controllers"; private const string Users = "users"; + private const string Admins = "Admins"; private const string RdsGroupFormat = "rds-{0}-{1}"; private const string RdsModuleName = "RemoteDesktopServices"; private const string AddNpsString = "netsh nps add np name=\"\"{0}\"\" policysource=\"1\" processingorder=\"{1}\" conditionid=\"0x3d\" conditiondata=\"^5$\" conditionid=\"0x1fb5\" conditiondata=\"{2}\" conditionid=\"0x1e\" conditiondata=\"UserAuthType:(PW|CA)\" profileid=\"0x1005\" profiledata=\"TRUE\" profileid=\"0x100f\" profiledata=\"TRUE\" profileid=\"0x1009\" profiledata=\"0x7\" profileid=\"0x1fe6\" profiledata=\"0x40000000\""; @@ -310,7 +311,8 @@ namespace WebsitePanel.Providers.RemoteDesktopServices //ActiveDirectoryUtils.AddObjectToGroup(GetComputerPath(ConnectionBroker), GetComputerGroupPath(organizationId, collection.Name)); } - CheckOrCreateHelpDeskComputerGroup(); + CheckOrCreateHelpDeskComputerGroup(); + string helpDeskGroupSamAccountName = CheckOrCreateAdGroup(GetHelpDeskGroupPath(RDSHelpDeskGroup), GetRootOUPath(), RDSHelpDeskGroup, RDSHelpDeskGroupDescription); if (!ActiveDirectoryUtils.AdObjectExists(GetUsersGroupPath(organizationId, collection.Name))) { @@ -347,7 +349,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices CreateLocalAdministratorsGroup(rdsServer.FqdName, runSpace); } - AddHelpDeskAdminsGroupToLocalAdmins(runSpace, rdsServer.FqdName); + AddAdGroupToLocalAdmins(runSpace, rdsServer.FqdName, helpDeskGroupSamAccountName); AddComputerToCollectionAdComputerGroup(organizationId, collection.Name, rdsServer); } } @@ -513,11 +515,13 @@ namespace WebsitePanel.Providers.RemoteDesktopServices foreach(var server in servers) { + RemoveGroupFromLocalAdmin(server.FqdName, server.Name, GetLocalAdminsGroupName(collectionName), runSpace); RemoveComputerFromCollectionAdComputerGroup(organizationId, collectionName, server); } ActiveDirectoryUtils.DeleteADObject(GetComputerGroupPath(organizationId, collectionName)); - ActiveDirectoryUtils.DeleteADObject(GetUsersGroupPath(organizationId, collectionName)); + ActiveDirectoryUtils.DeleteADObject(GetUsersGroupPath(organizationId, collectionName)); + ActiveDirectoryUtils.DeleteADObject(GetGroupPath(organizationId, collectionName, GetLocalAdminsGroupName(collectionName))); } catch (Exception e) { @@ -529,12 +533,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices } return result; - } - - public List GetCollectionUsers(string collectionName) - { - return GetUsersToCollectionAdGroup(collectionName); - } + } public bool SetUsersInCollection(string organizationId, string collectionName, List users) { @@ -542,7 +541,9 @@ namespace WebsitePanel.Providers.RemoteDesktopServices try { - SetUsersToCollectionAdGroup(collectionName, organizationId, users); + var usersGroupName = GetUsersGroupName(collectionName); + var usersGroupPath = GetUsersGroupPath(organizationId, collectionName); + SetUsersToCollectionAdGroup(collectionName, organizationId, users, usersGroupName, usersGroupPath); } catch (Exception e) { @@ -573,14 +574,15 @@ namespace WebsitePanel.Providers.RemoteDesktopServices ExecuteShellCommand(runSpace, cmd, false); - CheckOrCreateHelpDeskComputerGroup(); + CheckOrCreateHelpDeskComputerGroup(); + string helpDeskGroupSamAccountName = CheckOrCreateAdGroup(GetHelpDeskGroupPath(RDSHelpDeskGroup), GetRootOUPath(), RDSHelpDeskGroup, RDSHelpDeskGroupDescription); if (!CheckLocalAdminsGroupExists(server.FqdName, runSpace)) { CreateLocalAdministratorsGroup(server.FqdName, runSpace); } - AddHelpDeskAdminsGroupToLocalAdmins(runSpace, server.FqdName); + AddAdGroupToLocalAdmins(runSpace, server.FqdName, helpDeskGroupSamAccountName); AddComputerToCollectionAdComputerGroup(organizationId, collectionName, server); } catch (Exception e) @@ -616,6 +618,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices ExecuteShellCommand(runSpace, cmd, false); + RemoveGroupFromLocalAdmin(server.FqdName, server.Name, GetLocalAdminsGroupName(collectionName), runSpace); RemoveComputerFromCollectionAdComputerGroup(organizationId, collectionName, server); } finally @@ -978,7 +981,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices #region Local Admins - public void SaveRdsCollectionLocalAdmins(List users, List hosts) + public void SaveRdsCollectionLocalAdmins(List users, List hosts, string collectionName, string organizationId) { Runspace runspace = null; @@ -987,6 +990,10 @@ namespace WebsitePanel.Providers.RemoteDesktopServices runspace = OpenRunspace(); var index = ServerSettings.ADRootDomain.LastIndexOf("."); var domainName = ServerSettings.ADRootDomain; + string groupName = GetLocalAdminsGroupName(collectionName); + string groupPath = GetGroupPath(organizationId, collectionName, groupName); + string helpDeskGroupSamAccountName = CheckOrCreateAdGroup(GetHelpDeskGroupPath(RDSHelpDeskGroup), GetRootOUPath(), RDSHelpDeskGroup, RDSHelpDeskGroupDescription); + string localAdminsGroupSamAccountName = CheckOrCreateAdGroup(groupPath, GetOrganizationPath(organizationId), groupName, WspAdministratorsGroupDescription); if (index > 0) { @@ -1004,24 +1011,12 @@ namespace WebsitePanel.Providers.RemoteDesktopServices Log.WriteWarning(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray())); throw new Exception(string.Join("\r\n", errors.Select(e => e.ToString()).ToArray())); } - } - - var existingAdmins = GetExistingLocalAdmins(hostName, runspace).Select(e => e.ToLower()); - var formUsers = users.Select(u => string.Format("{0}\\{1}", domainName, u.SamAccountName).ToLower()); - var newUsers = users.Where(u => !existingAdmins.Contains(string.Format("{0}\\{1}", domainName, u.SamAccountName).ToLower())); - var removedUsers = existingAdmins.Where(e => !formUsers.Contains(e)); + } - foreach (var user in newUsers) - { - AddNewLocalAdmin(hostName, user.SamAccountName, runspace); - } + AddAdGroupToLocalAdmins(runspace, hostName, helpDeskGroupSamAccountName); + AddAdGroupToLocalAdmins(runspace, hostName, localAdminsGroupSamAccountName); - foreach (var user in removedUsers) - { - RemoveLocalAdmin(hostName, user, runspace); - } - - AddHelpDeskAdminsGroupToLocalAdmins(runspace, hostName); + SetUsersToCollectionAdGroup(collectionName, organizationId, users, GetLocalAdminsGroupName(collectionName), groupPath); } } finally @@ -1030,27 +1025,11 @@ namespace WebsitePanel.Providers.RemoteDesktopServices } } - public List GetRdsCollectionLocalAdmins(string hostName) - { - Runspace runspace = null; - var result = new List(); - - try - { - runspace = OpenRunspace(); - - if (CheckLocalAdminsGroupExists(hostName, runspace)) - { - result = GetExistingLocalAdmins(hostName, runspace); - } - } - finally - { - CloseRunspace(runspace); - } - - return result; - } + public List GetRdsCollectionLocalAdmins(string organizationId, string collectionName) + { + string groupName = GetLocalAdminsGroupName(collectionName); + return GetUsersToCollectionAdGroup(collectionName, groupName, organizationId); + } private bool CheckLocalAdminsGroupExists(string hostName, Runspace runspace) { @@ -1097,59 +1076,19 @@ namespace WebsitePanel.Providers.RemoteDesktopServices } return errors; - } - - private List GetExistingLocalAdmins(string hostName, Runspace runspace) - { - var result = new List(); - - var scripts = new List - { - string.Format("net localgroup {0} | select -skip 6", WspAdministratorsGroupName) - }; - - object[] errors = null; - var exitingAdmins = ExecuteRemoteShellCommand(runspace, hostName, scripts, out errors); - - if (!errors.Any()) - { - foreach(var user in exitingAdmins.Take(exitingAdmins.Count - 2)) - { - result.Add(user.ToString()); - } - } - - return result; - } - - private object[] AddNewLocalAdmin(string hostName, string samAccountName, Runspace runspace) - { + } + + private void RemoveGroupFromLocalAdmin(string fqdnName, string hostName, string groupName, Runspace runspace) + { var scripts = new List { string.Format("$GroupObj = [ADSI]\"WinNT://{0}/{1}\"", hostName, WspAdministratorsGroupName), - string.Format("$GroupObj.Add(\"WinNT://{0}/{1}\")", ServerSettings.ADRootDomain, samAccountName) + string.Format("$GroupObj.Remove(\"WinNT://{0}/{1}\")", ServerSettings.ADRootDomain, RDSHelpDeskGroup), + string.Format("$GroupObj.Remove(\"WinNT://{0}/{1}\")", ServerSettings.ADRootDomain, groupName) }; object[] errors = null; - ExecuteRemoteShellCommand(runspace, hostName, scripts, out errors); - - return errors; - } - - private object[] RemoveLocalAdmin(string hostName, string user, Runspace runspace) - { - var userObject = user.Split('\\'); - - var scripts = new List - { - string.Format("$GroupObj = [ADSI]\"WinNT://{0}/{1}\"", hostName, WspAdministratorsGroupName), - string.Format("$GroupObj.Remove(\"WinNT://{0}/{1}\")", userObject[0], userObject[1]) - }; - - object[] errors = null; - ExecuteRemoteShellCommand(runspace, hostName, scripts, out errors); - - return errors; + ExecuteRemoteShellCommand(runspace, fqdnName, scripts, out errors); } #endregion @@ -1177,23 +1116,22 @@ namespace WebsitePanel.Providers.RemoteDesktopServices } } - private void AddHelpDeskAdminsGroupToLocalAdmins(Runspace runspace, string hostName) - { - var helpDeskAdminsGroupPath = GetHelpDeskGroupPath(RDSHelpDeskGroup); + private string CheckOrCreateAdGroup(string groupPath, string rootPath, string groupName, string description) + { DirectoryEntry groupEntry = null; - if (!ActiveDirectoryUtils.AdObjectExists(helpDeskAdminsGroupPath)) + if (!ActiveDirectoryUtils.AdObjectExists(groupPath)) { - ActiveDirectoryUtils.CreateGroup(GetRootOUPath(), RDSHelpDeskGroup); - groupEntry = ActiveDirectoryUtils.GetADObject(helpDeskAdminsGroupPath); + ActiveDirectoryUtils.CreateGroup(rootPath, groupName); + groupEntry = ActiveDirectoryUtils.GetADObject(groupPath); if (groupEntry.Properties.Contains("Description")) { - groupEntry.Properties["Description"][0] = RDSHelpDeskGroupDescription; + groupEntry.Properties["Description"][0] = description; } else { - groupEntry.Properties["Description"].Add(RDSHelpDeskGroupDescription); + groupEntry.Properties["Description"].Add(description); } groupEntry.CommitChanges(); @@ -1201,11 +1139,14 @@ namespace WebsitePanel.Providers.RemoteDesktopServices if (groupEntry == null) { - groupEntry = ActiveDirectoryUtils.GetADObject(helpDeskAdminsGroupPath); + groupEntry = ActiveDirectoryUtils.GetADObject(groupPath); } - var samAccountName = ActiveDirectoryUtils.GetADObjectProperty(groupEntry, "sAMAccountName"); - + return ActiveDirectoryUtils.GetADObjectProperty(groupEntry, "sAMAccountName").ToString(); + } + + private void AddAdGroupToLocalAdmins(Runspace runspace, string hostName, string samAccountName) + { var scripts = new List { string.Format("$GroupObj = [ADSI]\"WinNT://{0}/{1}\"", hostName, WspAdministratorsGroupName), @@ -1227,7 +1168,7 @@ namespace WebsitePanel.Providers.RemoteDesktopServices try { var guid = Guid.NewGuid(); - var x509Cert = new X509Certificate2(certificate, password, X509KeyStorageFlags.Exportable); + var x509Cert = new X509Certificate2(certificate, password, X509KeyStorageFlags.Exportable); //var content = x509Cert.Export(X509ContentType.Pfx); var filePath = SaveCertificate(certificate, guid); runspace = OpenRunspace(); @@ -1355,21 +1296,17 @@ namespace WebsitePanel.Providers.RemoteDesktopServices return false; } - private void SetUsersToCollectionAdGroup(string collectionName, string organizationId, IEnumerable users) - { - var usersGroupName = GetUsersGroupName(collectionName); - var usersGroupPath = GetUsersGroupPath(organizationId, collectionName); + private void SetUsersToCollectionAdGroup(string collectionName, string organizationId, IEnumerable users, string groupName, string groupPath) + { var orgPath = GetOrganizationPath(organizationId); var orgEntry = ActiveDirectoryUtils.GetADObject(orgPath); - var groupUsers = ActiveDirectoryUtils.GetGroupObjects(usersGroupName, "user", orgEntry); - - //remove all users from group + var groupUsers = ActiveDirectoryUtils.GetGroupObjects(groupName, "user", orgEntry); + foreach (string userPath in groupUsers) { - ActiveDirectoryUtils.RemoveObjectFromGroup(userPath, usersGroupPath); + ActiveDirectoryUtils.RemoveObjectFromGroup(userPath, groupPath); } - - //adding users to group + foreach (var user in users) { var userPath = GetUserPath(organizationId, user); @@ -1377,20 +1314,19 @@ namespace WebsitePanel.Providers.RemoteDesktopServices if (ActiveDirectoryUtils.AdObjectExists(userPath)) { var userObject = ActiveDirectoryUtils.GetADObject(userPath); - var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(userObject, "sAMAccountName"); - var userGroupsPath = GetUsersGroupPath(organizationId, collectionName); - ActiveDirectoryUtils.AddObjectToGroup(userPath, userGroupsPath); + var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(userObject, "sAMAccountName"); + ActiveDirectoryUtils.AddObjectToGroup(userPath, groupPath); } } } - private List GetUsersToCollectionAdGroup(string collectionName) + private List GetUsersToCollectionAdGroup(string collectionName, string groupName, string organizationId) { - var users = new List(); + var users = new List(); + var orgPath = GetOrganizationPath(organizationId); + var orgEntry = ActiveDirectoryUtils.GetADObject(orgPath); - var usersGroupName = GetUsersGroupName(collectionName); - - foreach (string userPath in ActiveDirectoryUtils.GetGroupObjects(usersGroupName, "user")) + foreach (string userPath in ActiveDirectoryUtils.GetGroupObjects(groupName, "user", orgEntry)) { var userObject = ActiveDirectoryUtils.GetADObject(userPath); var samName = (string)ActiveDirectoryUtils.GetADObjectProperty(userObject, "sAMAccountName"); @@ -1738,6 +1674,11 @@ namespace WebsitePanel.Providers.RemoteDesktopServices return string.Format(RdsGroupFormat, collectionName, Users.ToLowerInvariant()); } + private string GetLocalAdminsGroupName(string collectionName) + { + return string.Format(RdsGroupFormat, collectionName, Admins.ToLowerInvariant()); + } + internal string GetComputerGroupPath(string organizationId, string collection) { StringBuilder sb = new StringBuilder(); @@ -1766,6 +1707,20 @@ namespace WebsitePanel.Providers.RemoteDesktopServices return sb.ToString(); } + private string GetGroupPath(string organizationId, string collectionName, string groupName) + { + StringBuilder sb = new StringBuilder(); + + AppendProtocol(sb); + AppendDomainController(sb); + AppendCNPath(sb, groupName); + AppendOUPath(sb, organizationId); + AppendOUPath(sb, RootOU); + AppendDomainPath(sb, RootDomain); + + return sb.ToString(); + } + private string GetUserPath(string organizationId, string loginName) { StringBuilder sb = new StringBuilder(); @@ -2290,18 +2245,22 @@ namespace WebsitePanel.Providers.RemoteDesktopServices cmd.Parameters.Add("CollectionName", collectionName); cmd.Parameters.Add("ConnectionBroker", ConnectionBroker); var userSessions = ExecuteShellCommand(runSpace, cmd, false, out errors); - var properties = typeof(RdsUserSession).GetProperties(); + var properties = typeof(RdsUserSession).GetProperties(); foreach(var userSession in userSessions) { - var session = new RdsUserSession(); - - foreach(var prop in properties) + var session = new RdsUserSession { - prop.SetValue(session, GetPSObjectProperty(userSession, prop.Name).ToString(), null); - } - - session.UserName = GetUserFullName(session.DomainName, session.UserName, runSpace); + CollectionName = GetPSObjectProperty(userSession, "CollectionName").ToString(), + DomainName = GetPSObjectProperty(userSession, "DomainName").ToString(), + HostServer = GetPSObjectProperty(userSession, "HostServer").ToString(), + SessionState = GetPSObjectProperty(userSession, "SessionState").ToString(), + UnifiedSessionId = GetPSObjectProperty(userSession, "UnifiedSessionId").ToString(), + SamAccountName = GetPSObjectProperty(userSession, "UserName").ToString(), + }; + + session.IsVip = false; + session.UserName = GetUserFullName(session.DomainName, session.SamAccountName, runSpace); result.Add(session); } diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs b/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs index 7d50298d..e9681bb1 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Client/RemoteDesktopServicesProxy.cs @@ -18,7 +18,6 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { using System.Web.Services.Protocols; using System; using System.Diagnostics; - using WebsitePanel.Providers.HostedSolution; /// @@ -1515,17 +1514,21 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { /// [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/server/SaveRdsCollectionLocalAdmins", RequestNamespace="http://smbsaas/websitepanel/server/", ResponseNamespace="http://smbsaas/websitepanel/server/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public void SaveRdsCollectionLocalAdmins(OrganizationUser[] users, string[] hosts) { + public void SaveRdsCollectionLocalAdmins(string[] users, string[] hosts, string organizationId, string collectionName) { this.Invoke("SaveRdsCollectionLocalAdmins", new object[] { users, - hosts}); + hosts, + organizationId, + collectionName}); } /// - public System.IAsyncResult BeginSaveRdsCollectionLocalAdmins(OrganizationUser[] users, string[] hosts, System.AsyncCallback callback, object asyncState) { + public System.IAsyncResult BeginSaveRdsCollectionLocalAdmins(string[] users, string[] hosts, string organizationId, string collectionName, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("SaveRdsCollectionLocalAdmins", new object[] { users, - hosts}, callback, asyncState); + hosts, + organizationId, + collectionName}, callback, asyncState); } /// @@ -1534,18 +1537,20 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { } /// - public void SaveRdsCollectionLocalAdminsAsync(OrganizationUser[] users, string[] hosts) { - this.SaveRdsCollectionLocalAdminsAsync(users, hosts, null); + public void SaveRdsCollectionLocalAdminsAsync(string[] users, string[] hosts, string organizationId, string collectionName) { + this.SaveRdsCollectionLocalAdminsAsync(users, hosts, organizationId, collectionName, null); } /// - public void SaveRdsCollectionLocalAdminsAsync(OrganizationUser[] users, string[] hosts, object userState) { + public void SaveRdsCollectionLocalAdminsAsync(string[] users, string[] hosts, string organizationId, string collectionName, object userState) { if ((this.SaveRdsCollectionLocalAdminsOperationCompleted == null)) { this.SaveRdsCollectionLocalAdminsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSaveRdsCollectionLocalAdminsOperationCompleted); } this.InvokeAsync("SaveRdsCollectionLocalAdmins", new object[] { users, - hosts}, this.SaveRdsCollectionLocalAdminsOperationCompleted, userState); + hosts, + organizationId, + collectionName}, this.SaveRdsCollectionLocalAdminsOperationCompleted, userState); } private void OnSaveRdsCollectionLocalAdminsOperationCompleted(object arg) { @@ -1558,16 +1563,18 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { /// [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/server/GetRdsCollectionLocalAdmins", RequestNamespace="http://smbsaas/websitepanel/server/", ResponseNamespace="http://smbsaas/websitepanel/server/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public string[] GetRdsCollectionLocalAdmins(string hostName) { + public string[] GetRdsCollectionLocalAdmins(string organizationId, string collectionName) { object[] results = this.Invoke("GetRdsCollectionLocalAdmins", new object[] { - hostName}); + organizationId, + collectionName}); return ((string[])(results[0])); } /// - public System.IAsyncResult BeginGetRdsCollectionLocalAdmins(string hostName, System.AsyncCallback callback, object asyncState) { + public System.IAsyncResult BeginGetRdsCollectionLocalAdmins(string organizationId, string collectionName, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("GetRdsCollectionLocalAdmins", new object[] { - hostName}, callback, asyncState); + organizationId, + collectionName}, callback, asyncState); } /// @@ -1577,17 +1584,18 @@ namespace WebsitePanel.Providers.RemoteDesktopServices { } /// - public void GetRdsCollectionLocalAdminsAsync(string hostName) { - this.GetRdsCollectionLocalAdminsAsync(hostName, null); + public void GetRdsCollectionLocalAdminsAsync(string organizationId, string collectionName) { + this.GetRdsCollectionLocalAdminsAsync(organizationId, collectionName, null); } /// - public void GetRdsCollectionLocalAdminsAsync(string hostName, object userState) { + public void GetRdsCollectionLocalAdminsAsync(string organizationId, string collectionName, object userState) { if ((this.GetRdsCollectionLocalAdminsOperationCompleted == null)) { this.GetRdsCollectionLocalAdminsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetRdsCollectionLocalAdminsOperationCompleted); } this.InvokeAsync("GetRdsCollectionLocalAdmins", new object[] { - hostName}, this.GetRdsCollectionLocalAdminsOperationCompleted, userState); + organizationId, + collectionName}, this.GetRdsCollectionLocalAdminsOperationCompleted, userState); } private void OnGetRdsCollectionLocalAdminsOperationCompleted(object arg) { diff --git a/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs b/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs index 038cc907..9e49fb21 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server/RemoteDesktopServices.asmx.cs @@ -566,12 +566,12 @@ namespace WebsitePanel.Server } [WebMethod, SoapHeader("settings")] - public void SaveRdsCollectionLocalAdmins(List users, List hosts) + public void SaveRdsCollectionLocalAdmins(List users, List hosts, string organizationId, string collectionName) { try { Log.WriteStart("'{0}' SaveRdsCollectionLocalAdmins", ProviderSettings.ProviderName); - RDSProvider.SaveRdsCollectionLocalAdmins(users, hosts); + RDSProvider.SaveRdsCollectionLocalAdmins(users, hosts, collectionName, organizationId); Log.WriteEnd("'{0}' SaveRdsCollectionLocalAdmins", ProviderSettings.ProviderName); } catch (Exception ex) @@ -582,12 +582,12 @@ namespace WebsitePanel.Server } [WebMethod, SoapHeader("settings")] - public List GetRdsCollectionLocalAdmins(string hostName) + public List GetRdsCollectionLocalAdmins(string organizationId, string collectionName) { try { Log.WriteStart("'{0}' GetRdsCollectionLocalAdmins", ProviderSettings.ProviderName); - var result = RDSProvider.GetRdsCollectionLocalAdmins(hostName); + var result = RDSProvider.GetRdsCollectionLocalAdmins(organizationId, collectionName); Log.WriteEnd("'{0}' GetRdsCollectionLocalAdmins", ProviderSettings.ProviderName); return result; diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx index 033cf7f3..27590807 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx @@ -5656,6 +5656,9 @@ Session host certificate not installed + + Session host certificate has been installed + RDS Collection settings not updated diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/RDSServers.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/RDSServers.ascx.resx index 4677be06..a769c20c 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/RDSServers.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/RDSServers.ascx.resx @@ -120,6 +120,9 @@ Add RDS Server + + Status + The list of RDS Servers is empty.<br><br>To add a new Server click "Add RDS Sever" button. diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Helpers/RDSHelper.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Helpers/RDSHelper.cs index 0e13992a..9b7c00d2 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Helpers/RDSHelper.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Helpers/RDSHelper.cs @@ -52,11 +52,15 @@ namespace WebsitePanel.Portal { rdsServers = ES.Services.RDS.GetRdsServersPaged("", filterValue, sortColumn, startRowIndex, maximumRows); - return rdsServers.Servers; - //return new RdsServer[] { new RdsServer { Name = "rds.1.server", FqdName = "", Address = "127.0.0.1" }, - // new RdsServer { Name = "rds.2.server", FqdName = "", Address = "127.0.0.2" }, - // new RdsServer { Name = "rds.3.server", FqdName = "", Address = "127.0.0.3" }, - // new RdsServer { Name = "rds.4.server", FqdName = "", Address = "127.0.0.4" }}; + foreach (var rdsServer in rdsServers.Servers) + { + if (rdsServer.ItemId.HasValue) + { + rdsServer.Status = ES.Services.RDS.GetRdsServerStatus(rdsServer.ItemId.Value, rdsServer.FqdName); + } + } + + return rdsServers.Servers; } public int GetOrganizationRdsServersPagedCount(int itemId, string filterValue) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/App_LocalResources/RDS_Settings.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/App_LocalResources/RDS_Settings.ascx.resx index f3221c01..1b443a76 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/App_LocalResources/RDS_Settings.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/App_LocalResources/RDS_Settings.ascx.resx @@ -126,4 +126,7 @@ Server Name + + Certificate Password: + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx index 879afc47..57dbeecb 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx @@ -1,5 +1,17 @@ <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="RDS_Settings.ascx.cs" Inherits="WebsitePanel.Portal.ProviderControls.RDS_Settings" %> - +
+ + + + + + + + -
+ + + +
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx.cs index 596af4e5..d85a1c61 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.Web.UI.WebControls; using WebsitePanel.EnterpriseServer; using WebsitePanel.Providers.Common; +using WebsitePanel.Providers.RemoteDesktopServices; namespace WebsitePanel.Portal.ProviderControls { @@ -54,11 +55,10 @@ namespace WebsitePanel.Portal.ProviderControls } public void BindSettings(System.Collections.Specialized.StringDictionary settings) - { + { txtConnectionBroker.Text = settings["ConnectionBroker"]; GWServers = settings["GWServrsList"]; - UpdateLyncServersGrid(); txtRootOU.Text = settings["RootOU"]; @@ -86,7 +86,26 @@ namespace WebsitePanel.Portal.ProviderControls settings["UseCentralNPS"] = chkUseCentralNPS.Checked.ToString(); settings["CentralNPS"] = chkUseCentralNPS.Checked ? txtCentralNPS.Text : string.Empty; - settings["GWServrsList"] = GWServers; + settings["GWServrsList"] = GWServers; + + try + { + if (upPFX.HasFile.Equals(true)) + { + var certificate = new RdsCertificate + { + ServiceId = PanelRequest.ServiceId, + Content = Convert.ToBase64String(upPFX.FileBytes), + FileName = upPFX.FileName, + Hash = txtPFXInstallPassword.Text + }; + + ES.Services.RDS.AddRdsCertificate(certificate); + } + } + catch (Exception) + { + } } protected void chkUseCentralNPS_CheckedChanged(object sender, EventArgs e) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx.designer.cs index f0638a0c..9e1ba55e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ProviderControls/RDS_Settings.ascx.designer.cs @@ -1,31 +1,3 @@ -// Copyright (c) 2015, Outercurve Foundation. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// - Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// -// - Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// - Neither the name of the Outercurve Foundation nor the names of its -// contributors may be used to endorse or promote products derived from this -// software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - //------------------------------------------------------------------------------ // // This code was generated by a tool. @@ -40,6 +12,24 @@ namespace WebsitePanel.Portal.ProviderControls { public partial class RDS_Settings { + /// + /// upPFX control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.FileUpload upPFX; + + /// + /// txtPFXInstallPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtPFXInstallPassword; + /// /// lblConnectionBroker control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/AssignedRDSServers.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/AssignedRDSServers.ascx.resx index 33277c17..e2d6204d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/AssignedRDSServers.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/AssignedRDSServers.ascx.resx @@ -145,7 +145,7 @@ Assigned RDS Servers - Total RDS Servers Allocated: + Total Remote Desktop Servers Allocated: Disable diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSCollections.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSCollections.ascx.resx index b231aa48..3a2deaac 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSCollections.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSCollections.ascx.resx @@ -147,4 +147,7 @@ RDS Server + + Total Remote Desktop Collections Created: + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditApplicationUsers.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditApplicationUsers.ascx.resx index eb391f90..4d916746 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditApplicationUsers.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditApplicationUsers.ascx.resx @@ -153,4 +153,10 @@ Application Name + + Back to Applications List + + + Save Changes and Exit + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionUsers.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionUsers.ascx.resx index b7086125..60f1cf4b 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionUsers.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/App_LocalResources/RDSEditCollectionUsers.ascx.resx @@ -144,4 +144,7 @@ RDS Users + + Total RDS Users Assigned: + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/AssignedRDSServers.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/AssignedRDSServers.ascx index 6016913e..9ff6017f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/AssignedRDSServers.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/AssignedRDSServers.ascx @@ -72,6 +72,11 @@ +
+ +     + +
// This code was generated by a tool. @@ -139,6 +111,24 @@ namespace WebsitePanel.Portal.RDS { /// protected global::System.Web.UI.WebControls.GridView gvRDSAssignedServers; + /// + /// locQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locQuota; + + /// + /// rdsServersQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.QuotaViewer rdsServersQuota; + /// /// odsRDSAssignedServersPaged control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx index a311aaa3..a5369d97 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCollections.ascx @@ -66,6 +66,11 @@ +
+ +     + +
protected global::System.Web.UI.WebControls.GridView gvRDSCollections; + /// + /// locQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locQuota; + + /// + /// collectionsQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.QuotaViewer collectionsQuota; + /// /// odsRDSCollectionsPaged control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx index e7277028..9549a550 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx @@ -28,27 +28,7 @@
- - - - - -
-
-
- -
-
- -
-
- -
-
-
-
+
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.cs index 21ef3c4d..2d21ad7e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.cs @@ -63,21 +63,7 @@ namespace WebsitePanel.Portal.RDS } RdsCollection collection = new RdsCollection{ Name = txtCollectionName.Text, DisplayName = txtCollectionName.Text, Servers = servers.GetServers(), Description = "" }; - int collectionId = ES.Services.RDS.AddRdsCollection(PanelRequest.ItemID, collection); - - try - { - if (upPFX.HasFile.Equals(true)) - { - byte[] pfx = upPFX.FileBytes; - string certPassword = txtPFXInstallPassword.Text; - //ES.Services.RDS.InstallSessionHostsCertificate(collectionId, pfx, certPassword); - } - } - catch(Exception ex) - { - messageBox.ShowErrorMessage("RDSSESSIONHOST_CERTIFICATE_NOT_INSTALLED", ex); - } + int collectionId = ES.Services.RDS.AddRdsCollection(PanelRequest.ItemID, collection); Response.Redirect(EditUrl("SpaceID", PanelSecurity.PackageId.ToString(), "rds_edit_collection", "CollectionId=" + collectionId, "ItemID=" + PanelRequest.ItemID)); } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.designer.cs index f61636b8..b1666d95 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSCreateCollection.ascx.designer.cs @@ -75,42 +75,6 @@ namespace WebsitePanel.Portal.RDS { /// protected global::System.Web.UI.WebControls.RequiredFieldValidator valCollectionName; - /// - /// secSelectSertificate control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::WebsitePanel.Portal.CollapsiblePanel secSelectSertificate; - - /// - /// panelSelectSertificate control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel panelSelectSertificate; - - /// - /// upPFX control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.FileUpload upPFX; - - /// - /// txtPFXInstallPassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox txtPFXInstallPassword; - /// /// RDSServersPanel control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx index 6095f06d..e7cf4275 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx @@ -55,8 +55,12 @@
- + + +
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx.cs index 41bdec12..2a9be753 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx.cs @@ -100,5 +100,10 @@ namespace WebsitePanel.Portal.RDS Response.Redirect(EditUrl("SpaceID", PanelSecurity.PackageId.ToString(), "rds_collection_edit_apps", "CollectionId=" + PanelRequest.CollectionID, "ItemID=" + PanelRequest.ItemID)); } } + + protected void btnExit_Click(object sender, EventArgs e) + { + Response.Redirect(EditUrl("SpaceID", PanelSecurity.PackageId.ToString(), "rds_collection_edit_apps", "CollectionId=" + PanelRequest.CollectionID, "ItemID=" + PanelRequest.ItemID)); + } } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx.designer.cs index fd65d541..62030191 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditApplicationUsers.ascx.designer.cs @@ -139,12 +139,30 @@ namespace WebsitePanel.Portal.RDS { protected global::WebsitePanel.Portal.RDS.UserControls.RDSCollectionUsers users; /// - /// buttonPanel control. + /// btnSave control. /// /// /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// - protected global::WebsitePanel.Portal.ItemButtonPanel buttonPanel; + protected global::System.Web.UI.WebControls.Button btnSave; + + /// + /// btnSaveExit control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnSaveExit; + + /// + /// btnExit control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnExit; } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx index 7f71695d..57a37195 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx @@ -1,6 +1,7 @@ <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="RDSEditCollectionUsers.ascx.cs" Inherits="WebsitePanel.Portal.RDS.RDSEditCollectionUsers" %> <%@ Register Src="../UserControls/SimpleMessageBox.ascx" TagName="SimpleMessageBox" TagPrefix="wsp" %> <%@ Register Src="../UserControls/EnableAsyncTasksSupport.ascx" TagName="EnableAsyncTasksSupport" TagPrefix="wsp" %> +<%@ Register Src="../UserControls/QuotaViewer.ascx" TagName="QuotaViewer" TagPrefix="wsp" %> <%@ Register Src="UserControls/RDSCollectionUsers.ascx" TagName="CollectionUsers" TagPrefix="wsp"%> <%@ Register Src="UserControls/RDSCollectionTabs.ascx" TagName="CollectionTabs" TagPrefix="wsp" %> <%@ Register TagPrefix="wsp" TagName="CollapsiblePanel" Src="../UserControls/CollapsiblePanel.ascx" %> @@ -34,6 +35,11 @@ +
+ +     + +
diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.cs index beaeed58..767eab4f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.cs @@ -39,9 +39,10 @@ namespace WebsitePanel.Portal.RDS { protected void Page_Load(object sender, EventArgs e) - { + { if (!IsPostBack) { + BindQuota(); var collectionUsers = ES.Services.RDS.GetRdsCollectionUsers(PanelRequest.CollectionID); var collection = ES.Services.RDS.GetRdsCollection(PanelRequest.CollectionID); @@ -50,6 +51,20 @@ namespace WebsitePanel.Portal.RDS } } + private void BindQuota() + { + PackageContext cntx = PackagesHelper.GetCachedPackageContext(PanelSecurity.PackageId); + OrganizationStatistics stats = ES.Services.Organizations.GetOrganizationStatisticsByOrganization(PanelRequest.ItemID); + OrganizationStatistics tenantStats = ES.Services.Organizations.GetOrganizationStatistics(PanelRequest.ItemID); + usersQuota.QuotaUsedValue = stats.CreatedRdsUsers; + usersQuota.QuotaValue = stats.AllocatedRdsUsers; + + if (stats.AllocatedUsers != -1) + { + usersQuota.QuotaAvailable = tenantStats.AllocatedRdsUsers - tenantStats.CreatedRdsUsers; + } + } + private bool SaveRdsUsers() { try @@ -73,6 +88,7 @@ namespace WebsitePanel.Portal.RDS } SaveRdsUsers(); + BindQuota(); } protected void btnSaveExit_Click(object sender, EventArgs e) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.designer.cs index b4cdce32..e584e549 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSEditCollectionUsers.ascx.designer.cs @@ -93,6 +93,24 @@ namespace WebsitePanel.Portal.RDS { /// protected global::WebsitePanel.Portal.RDS.UserControls.RDSCollectionUsers users; + /// + /// locQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locQuota; + + /// + /// usersQuota control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.QuotaViewer usersQuota; + /// /// buttonPanel control. /// diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx index 642ed06a..9afc8a5b 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx @@ -38,10 +38,11 @@ - + + diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx.cs index 79e37ea8..9938e16e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/RDSUserSessions.ascx.cs @@ -5,6 +5,8 @@ using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; +using WebsitePanel.EnterpriseServer; +using WebsitePanel.Providers.HostedSolution; using WebsitePanel.Providers.RemoteDesktopServices; namespace WebsitePanel.Portal.RDS @@ -101,5 +103,15 @@ namespace WebsitePanel.Portal.RDS gvRDSUserSessions.DataSource = userSessions; gvRDSUserSessions.DataBind(); } + + public string GetAccountImage(bool vip) + { + if (vip) + { + return GetThemedImage("Exchange/vip_user_16.png"); + } + + return GetThemedImage("Exchange/accounting_mail_16.png"); + } } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx.cs index 15bf0ecc..0474d715 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDS/UserControls/RDSCollectionApps.ascx.cs @@ -210,7 +210,7 @@ namespace WebsitePanel.Portal.RDS.UserControls RemoteApplication app = new RemoteApplication(); app.Alias = (string)gvApps.DataKeys[i][0]; - app.DisplayName = ((HyperLink)row.FindControl("lnkDisplayName")).Text; + app.DisplayName = ((LinkButton)row.FindControl("lnkDisplayName")).Text; app.FilePath = ((HiddenField)row.FindControl("hfFilePath")).Value; app.RequiredCommandLine = ((HiddenField)row.FindControl("hfRequiredCommandLine")).Value; diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDSServers.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDSServers.ascx index 0aa32a4e..c38baf43 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDSServers.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/RDSServers.ascx @@ -5,11 +5,18 @@ <%@ Register Src="UserControls/UserDetails.ascx" TagName="UserDetails" TagPrefix="uc2" %> <%@ Register Src="UserControls/CollapsiblePanel.ascx" TagName="CollapsiblePanel" TagPrefix="wsp" %> <%@ Register Src="UserControls/SimpleMessageBox.ascx" TagName="SimpleMessageBox" TagPrefix="wsp" %> +<%@ Register Src="UserControls/PopupHeader.ascx" TagName="PopupHeader" TagPrefix="wsp" %> +<%@ Register Src="UserControls/EnableAsyncTasksSupport.ascx" TagName="EnableAsyncTasksSupport" TagPrefix="wsp" %> - - + + + + + + +
@@ -43,11 +50,45 @@ - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + +