diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index f5b6d176..43fabbd1 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -4338,3 +4338,9 @@ WHERE RETURN GO + +IF NOT EXISTS (SELECT * FROM [dbo].[Quotas] WHERE [QuotaName] = 'EnterpriseStorage.DriveMaps') +BEGIN +INSERT [dbo].[Quotas] ([QuotaID], [GroupID],[QuotaOrder], [QuotaName], [QuotaDescription], [QuotaTypeID], [ServiceQuota], [ItemTypeID]) VALUES (468, 44, 2, N'EnterpriseStorage.DriveMaps', N'Use Drive Maps', 1, 0, NULL) +END +GO diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Packages/Quotas.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Packages/Quotas.cs index a351f386..c3e2660e 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Packages/Quotas.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Base/Packages/Quotas.cs @@ -250,7 +250,8 @@ order by rg.groupOrder public const string HELICON_ZOO = "HeliconZoo.*"; public const string ENTERPRISESTORAGE_DISKSTORAGESPACE = "EnterpriseStorage.DiskStorageSpace"; - public const string ENTERPRISESTORAGE_FOLDERS = "EnterpriseStorage.Folders"; + public const string ENTERPRISESTORAGE_FOLDERS = "EnterpriseStorage.Folders"; + public const string ENTERPRICESTORAGE_DRIVEMAPS = "EnterpriseStorage.DriveMaps"; } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/EnterpriseStorageProxy.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/EnterpriseStorageProxy.cs index b02f51d3..85b215ef 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/EnterpriseStorageProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Client/EnterpriseStorageProxy.cs @@ -92,6 +92,16 @@ namespace WebsitePanel.EnterpriseServer private System.Threading.SendOrPostCallback GetStatisticsByOrganizationOperationCompleted; + private System.Threading.SendOrPostCallback CreateMappedDriveOperationCompleted; + + private System.Threading.SendOrPostCallback DeleteMappedDriveOperationCompleted; + + private System.Threading.SendOrPostCallback GetDriveMapsPagedOperationCompleted; + + private System.Threading.SendOrPostCallback GetUsedDriveLettersOperationCompleted; + + private System.Threading.SendOrPostCallback GetNotMappedEnterpriseFoldersOperationCompleted; + /// public esEnterpriseStorage() { @@ -152,6 +162,21 @@ namespace WebsitePanel.EnterpriseServer /// public event GetStatisticsByOrganizationCompletedEventHandler GetStatisticsByOrganizationCompleted; + /// + public event CreateMappedDriveCompletedEventHandler CreateMappedDriveCompleted; + + /// + public event DeleteMappedDriveCompletedEventHandler DeleteMappedDriveCompleted; + + /// + public event GetDriveMapsPagedCompletedEventHandler GetDriveMapsPagedCompleted; + + /// + public event GetUsedDriveLettersCompletedEventHandler GetUsedDriveLettersCompleted; + + /// + public event GetNotMappedEnterpriseFoldersCompletedEventHandler GetNotMappedEnterpriseFoldersCompleted; + /// [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/CheckFileServicesInstallation", 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 bool CheckFileServicesInstallation(int serviceId) @@ -1115,6 +1140,278 @@ namespace WebsitePanel.EnterpriseServer } } + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/CreateMappedDrive", 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 CreateMappedDrive(int packageId, int itemId, string driveLetter, string labelAs, string folderName) + { + object[] results = this.Invoke("CreateMappedDrive", new object[] { + packageId, + itemId, + driveLetter, + labelAs, + folderName}); + return ((ResultObject)(results[0])); + } + + /// + public System.IAsyncResult BeginCreateMappedDrive(int packageId, int itemId, string driveLetter, string labelAs, string folderName, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("CreateMappedDrive", new object[] { + packageId, + itemId, + driveLetter, + labelAs, + folderName}, callback, asyncState); + } + + /// + public ResultObject EndCreateMappedDrive(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((ResultObject)(results[0])); + } + + /// + public void CreateMappedDriveAsync(int packageId, int itemId, string driveLetter, string labelAs, string folderName) + { + this.CreateMappedDriveAsync(packageId, itemId, driveLetter, labelAs, folderName, null); + } + + /// + public void CreateMappedDriveAsync(int packageId, int itemId, string driveLetter, string labelAs, string folderName, object userState) + { + if ((this.CreateMappedDriveOperationCompleted == null)) + { + this.CreateMappedDriveOperationCompleted = new System.Threading.SendOrPostCallback(this.OnCreateMappedDriveOperationCompleted); + } + this.InvokeAsync("CreateMappedDrive", new object[] { + packageId, + itemId, + driveLetter, + labelAs, + folderName}, this.CreateMappedDriveOperationCompleted, userState); + } + + private void OnCreateMappedDriveOperationCompleted(object arg) + { + if ((this.CreateMappedDriveCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.CreateMappedDriveCompleted(this, new CreateMappedDriveCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/DeleteMappedDrive", 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 DeleteMappedDrive(int itemId, string driveLetter) + { + object[] results = this.Invoke("DeleteMappedDrive", new object[] { + itemId, + driveLetter}); + return ((ResultObject)(results[0])); + } + + /// + public System.IAsyncResult BeginDeleteMappedDrive(int itemId, string driveLetter, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("DeleteMappedDrive", new object[] { + itemId, + driveLetter}, callback, asyncState); + } + + /// + public ResultObject EndDeleteMappedDrive(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((ResultObject)(results[0])); + } + + /// + public void DeleteMappedDriveAsync(int itemId, string driveLetter) + { + this.DeleteMappedDriveAsync(itemId, driveLetter, null); + } + + /// + public void DeleteMappedDriveAsync(int itemId, string driveLetter, object userState) + { + if ((this.DeleteMappedDriveOperationCompleted == null)) + { + this.DeleteMappedDriveOperationCompleted = new System.Threading.SendOrPostCallback(this.OnDeleteMappedDriveOperationCompleted); + } + this.InvokeAsync("DeleteMappedDrive", new object[] { + itemId, + driveLetter}, this.DeleteMappedDriveOperationCompleted, userState); + } + + private void OnDeleteMappedDriveOperationCompleted(object arg) + { + if ((this.DeleteMappedDriveCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.DeleteMappedDriveCompleted(this, new DeleteMappedDriveCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/GetDriveMapsPaged", 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 MappedDrivesPaged GetDriveMapsPaged(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows) + { + object[] results = this.Invoke("GetDriveMapsPaged", new object[] { + itemId, + filterValue, + sortColumn, + startRow, + maximumRows}); + return ((MappedDrivesPaged)(results[0])); + } + + /// + public System.IAsyncResult BeginGetDriveMapsPaged(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("GetDriveMapsPaged", new object[] { + itemId, + filterValue, + sortColumn, + startRow, + maximumRows}, callback, asyncState); + } + + /// + public MappedDrivesPaged EndGetDriveMapsPaged(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((MappedDrivesPaged)(results[0])); + } + + /// + public void GetDriveMapsPagedAsync(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows) + { + this.GetDriveMapsPagedAsync(itemId, filterValue, sortColumn, startRow, maximumRows, null); + } + + /// + public void GetDriveMapsPagedAsync(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows, object userState) + { + if ((this.GetDriveMapsPagedOperationCompleted == null)) + { + this.GetDriveMapsPagedOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetDriveMapsPagedOperationCompleted); + } + this.InvokeAsync("GetDriveMapsPaged", new object[] { + itemId, + filterValue, + sortColumn, + startRow, + maximumRows}, this.GetDriveMapsPagedOperationCompleted, userState); + } + + private void OnGetDriveMapsPagedOperationCompleted(object arg) + { + if ((this.GetDriveMapsPagedCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.GetDriveMapsPagedCompleted(this, new GetDriveMapsPagedCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/GetUsedDriveLetters", 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 string[] GetUsedDriveLetters(int itemId) + { + object[] results = this.Invoke("GetUsedDriveLetters", new object[] { + itemId}); + return ((string[])(results[0])); + } + + /// + public System.IAsyncResult BeginGetUsedDriveLetters(int itemId, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("GetUsedDriveLetters", new object[] { + itemId}, callback, asyncState); + } + + /// + public string[] EndGetUsedDriveLetters(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((string[])(results[0])); + } + + /// + public void GetUsedDriveLettersAsync(int itemId) + { + this.GetUsedDriveLettersAsync(itemId, null); + } + + /// + public void GetUsedDriveLettersAsync(int itemId, object userState) + { + if ((this.GetUsedDriveLettersOperationCompleted == null)) + { + this.GetUsedDriveLettersOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetUsedDriveLettersOperationCompleted); + } + this.InvokeAsync("GetUsedDriveLetters", new object[] { + itemId}, this.GetUsedDriveLettersOperationCompleted, userState); + } + + private void OnGetUsedDriveLettersOperationCompleted(object arg) + { + if ((this.GetUsedDriveLettersCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.GetUsedDriveLettersCompleted(this, new GetUsedDriveLettersCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://smbsaas/websitepanel/enterpriseserver/GetNotMappedEnterpriseFolders", 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 SystemFile[] GetNotMappedEnterpriseFolders(int itemId) + { + object[] results = this.Invoke("GetNotMappedEnterpriseFolders", new object[] { + itemId}); + return ((SystemFile[])(results[0])); + } + + /// + public System.IAsyncResult BeginGetNotMappedEnterpriseFolders(int itemId, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("GetNotMappedEnterpriseFolders", new object[] { + itemId}, callback, asyncState); + } + + /// + public SystemFile[] EndGetNotMappedEnterpriseFolders(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((SystemFile[])(results[0])); + } + + /// + public void GetNotMappedEnterpriseFoldersAsync(int itemId) + { + this.GetNotMappedEnterpriseFoldersAsync(itemId, null); + } + + /// + public void GetNotMappedEnterpriseFoldersAsync(int itemId, object userState) + { + if ((this.GetNotMappedEnterpriseFoldersOperationCompleted == null)) + { + this.GetNotMappedEnterpriseFoldersOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetNotMappedEnterpriseFoldersOperationCompleted); + } + this.InvokeAsync("GetNotMappedEnterpriseFolders", new object[] { + itemId}, this.GetNotMappedEnterpriseFoldersOperationCompleted, userState); + } + + private void OnGetNotMappedEnterpriseFoldersOperationCompleted(object arg) + { + if ((this.GetNotMappedEnterpriseFoldersCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.GetNotMappedEnterpriseFoldersCompleted(this, new GetNotMappedEnterpriseFoldersCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// public new void CancelAsync(object userState) { @@ -1609,4 +1906,154 @@ namespace WebsitePanel.EnterpriseServer } } } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void CreateMappedDriveCompletedEventHandler(object sender, CreateMappedDriveCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class CreateMappedDriveCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal CreateMappedDriveCompletedEventArgs(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])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void DeleteMappedDriveCompletedEventHandler(object sender, DeleteMappedDriveCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class DeleteMappedDriveCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal DeleteMappedDriveCompletedEventArgs(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])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void GetDriveMapsPagedCompletedEventHandler(object sender, GetDriveMapsPagedCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class GetDriveMapsPagedCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal GetDriveMapsPagedCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) + { + this.results = results; + } + + /// + public MappedDrivesPaged Result + { + get + { + this.RaiseExceptionIfNecessary(); + return ((MappedDrivesPaged)(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void GetUsedDriveLettersCompletedEventHandler(object sender, GetUsedDriveLettersCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class GetUsedDriveLettersCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal GetUsedDriveLettersCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) + { + this.results = results; + } + + /// + public string[] Result + { + get + { + this.RaiseExceptionIfNecessary(); + return ((string[])(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void GetNotMappedEnterpriseFoldersCompletedEventHandler(object sender, GetNotMappedEnterpriseFoldersCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class GetNotMappedEnterpriseFoldersCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal GetNotMappedEnterpriseFoldersCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) + { + this.results = results; + } + + /// + public SystemFile[] Result + { + get + { + this.RaiseExceptionIfNecessary(); + return ((SystemFile[])(this.results[0])); + } + } + } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs index 42044528..058461da 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/EnterpriseStorage/EnterpriseStorageController.cs @@ -305,7 +305,7 @@ namespace WebsitePanel.EnterpriseServer EnterpriseStorageController.DeleteWebDavDirectory(packageId, usersDomain, org.OrganizationId); EnterpriseStorageController.DeleteFolder(itemId); - + EnterpriseStorageController.DeleteMappedDrivesGPO(itemId); } } catch (Exception ex) @@ -577,6 +577,12 @@ namespace WebsitePanel.EnterpriseServer es.DeleteFolder(org.OrganizationId, folderName, webDavSetting); + string path = string.Format(@"\\{0}@SSL\{1}\{2}", webDavSetting.Domain.Split('.')[0], org.OrganizationId, folderName); + + Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId); + + orgProxy.DeleteMappedDriveByPath(org.OrganizationId, path); + DataProvider.DeleteEnterpriseFolder(itemId, folderName); } catch (Exception ex) @@ -659,6 +665,21 @@ namespace WebsitePanel.EnterpriseServer List folders = es.GetFolders(org.OrganizationId, webDavSettings).Where(x => x.Name.Contains(filterValue)).ToList(); + Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId); + + List mappedDrives = orgProxy.GetDriveMaps(org.OrganizationId).ToList(); + + foreach (MappedDrive drive in mappedDrives) + { + foreach (SystemFile folder in folders) + { + if (drive.Path.Split('\\').Last() == folder.Name) + { + folder.DriveLetter = drive.DriveLetter; + } + } + } + switch (sortColumn) { case "Size": @@ -786,6 +807,8 @@ namespace WebsitePanel.EnterpriseServer DataProvider.GetEnterpriseFolder(itemId, folder)); es.SetFolderWebDavRules(org.OrganizationId, folder, webDavSetting, rules); + + EnterpriseStorageController.SetDriveMapsTargetingFilter(org, permission, folder); } catch (Exception ex) { @@ -890,6 +913,7 @@ namespace WebsitePanel.EnterpriseServer || account.AccountType == ExchangeAccountType.DefaultSecurityGroup) { rule.Roles.Add(permission.Account); + permission.IsGroup = true; } else { @@ -1196,5 +1220,331 @@ namespace WebsitePanel.EnterpriseServer } #endregion + + #region Drive Mapping + + public static ResultObject CreateMappedDrive(int packageId, int itemId, string driveLetter, string labelAs, string folderName) + { + return CreateMappedDriveInternal(packageId, itemId, driveLetter, labelAs, folderName); + } + + protected static ResultObject CreateMappedDriveInternal(int packageId, int itemId, string driveLetter, string labelAs, string folderName) + { + ResultObject result = TaskManager.StartResultTask("ENTERPRISE_STORAGE", "CREATE_MAPPED_DRIVE", itemId); + + try + { + // load organization + Organization org = OrganizationController.GetOrganization(itemId); + if (org == null) + { + result.IsSuccess = false; + result.AddError("", new NullReferenceException("Organization not found")); + return result; + } + + int esServiceId = PackageController.GetPackageServiceId(packageId, ResourceGroups.EnterpriseStorage); + + if (esServiceId != 0) + { + var webDavSetting = ObjectUtils.FillObjectFromDataReader( + DataProvider.GetEnterpriseFolder(itemId, folderName)); + + string path = string.Format(@"\\{0}@SSL\{1}\{2}", webDavSetting.Domain.Split('.')[0], org.OrganizationId, folderName); + + Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId); + + if (orgProxy.CreateMappedDrive(org.OrganizationId, driveLetter, labelAs, path) == 0) + { + var folder = GetFolder(itemId, folderName); + + EnterpriseStorageController.SetDriveMapsTargetingFilter(org, ConvertToESPermission(itemId, folder.Rules), folderName); + } + else + { + result.AddError("", new Exception("Organization already has mapped drive for this folder")); + return result; + } + } + } + catch (Exception ex) + { + result.AddError("ENTERPRISE_STORAGE_CREATE_MAPPED_DRIVE", ex); + } + finally + { + if (!result.IsSuccess) + { + TaskManager.CompleteResultTask(result); + } + else + { + TaskManager.CompleteResultTask(); + } + } + + return result; + } + + public static ResultObject DeleteMappedDrive(int itemId, string driveLetter) + { + return DeleteMappedDriveInternal(itemId, driveLetter); + } + + protected static ResultObject DeleteMappedDriveInternal(int itemId, string driveLetter) + { + ResultObject result = TaskManager.StartResultTask("ENTERPRISE_STORAGE", "DELETE_MAPPED_DRIVE", itemId); + + try + { + // load organization + Organization org = OrganizationController.GetOrganization(itemId); + if (org == null) + { + result.IsSuccess = false; + result.AddError("", new NullReferenceException("Organization not found")); + return result; + } + + Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId); + + orgProxy.DeleteMappedDrive(org.OrganizationId, driveLetter); + } + catch (Exception ex) + { + result.AddError("ENTERPRISE_STORAGE_DELETE_MAPPED_DRIVE", ex); + } + finally + { + if (!result.IsSuccess) + { + TaskManager.CompleteResultTask(result); + } + else + { + TaskManager.CompleteResultTask(); + } + } + + return result; + } + + public static MappedDrivesPaged GetDriveMapsPaged(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows) + { + return GetDriveMapsPagedInternal(itemId, filterValue, sortColumn, startRow, maximumRows); + } + + protected static MappedDrivesPaged GetDriveMapsPagedInternal(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows) + { + MappedDrivesPaged result = new MappedDrivesPaged(); + + try + { + // load organization + Organization org = OrganizationController.GetOrganization(itemId); + + if (org == null) + { + return null; + } + + EnterpriseStorage es = GetEnterpriseStorage(GetEnterpriseStorageServiceID(org.PackageId)); + + var webDavSettings = ObjectUtils.CreateListFromDataReader( + DataProvider.GetEnterpriseFolders(itemId)).ToArray(); + + List folders = es.GetFolders(org.OrganizationId, webDavSettings).ToList(); + + Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId); + + List mappedDrives = orgProxy.GetDriveMaps(org.OrganizationId).Where(x => x.LabelAs.Contains(filterValue)).ToList(); + List resultItems = new List(); + + foreach (MappedDrive drive in mappedDrives) + { + foreach (SystemFile folder in folders) + { + if (drive.Path.Split('\\').Last() == folder.Name) + { + drive.Folder = folder; + resultItems.Add(drive); + } + } + } + + mappedDrives = resultItems; + + switch (sortColumn) + { + case "Label": + mappedDrives = mappedDrives.OrderBy(x => x.LabelAs).ToList(); + break; + default: + mappedDrives = mappedDrives.OrderBy(x => x.DriveLetter).ToList(); + break; + } + + result.RecordsCount = mappedDrives.Count; + result.PageItems = mappedDrives.Skip(startRow).Take(maximumRows).ToArray(); + + } + catch (Exception ex) { throw ex; } + + return result; + } + + public static string[] GetUsedDriveLetters(int itemId) + { + return GetUsedDriveLettersInternal(itemId); + } + + protected static string[] GetUsedDriveLettersInternal(int itemId) + { + List driveLetters = new List(); + + try + { + // load organization + Organization org = OrganizationController.GetOrganization(itemId); + + if (org == null) + { + return null; + } + + Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId); + + driveLetters = orgProxy.GetDriveMaps(org.OrganizationId).Select(x => x.DriveLetter).ToList(); + } + catch (Exception ex) { throw ex; } + + return driveLetters.ToArray(); + + } + + public static SystemFile[] GetNotMappedEnterpriseFolders(int itemId) + { + return GetNotMappedEnterpriseFoldersInternal(itemId); + } + + protected static SystemFile[] GetNotMappedEnterpriseFoldersInternal(int itemId) + { + List folders = new List(); + try + { + // load organization + Organization org = OrganizationController.GetOrganization(itemId); + + if (org == null) + { + return null; + } + + if (CheckUsersDomainExistsInternal(itemId, org.PackageId)) + { + EnterpriseStorage es = GetEnterpriseStorage(GetEnterpriseStorageServiceID(org.PackageId)); + + var webDavSettings = ObjectUtils.CreateListFromDataReader( + DataProvider.GetEnterpriseFolders(itemId)).ToArray(); + + folders = es.GetFolders(org.OrganizationId, webDavSettings).ToList(); + + Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId); + + List drives = orgProxy.GetDriveMaps(org.OrganizationId).ToList(); + + foreach (MappedDrive drive in drives) + { + foreach (SystemFile folder in folders) + { + if (drive.Path.Split('\\').Last() == folder.Name) + { + folders.Remove(folder); + break; + } + } + } + } + } + catch (Exception ex) { throw ex; } + + return folders.ToArray(); + } + + private static ResultObject SetDriveMapsTargetingFilter(Organization org, ESPermission[] permissions, string folderName) + { + ResultObject result = TaskManager.StartResultTask("ENTERPRISE_STORAGE", "SET_MAPPED_DRIVE_TARGETING_FILTER"); + + try + { + Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId); + + List accounts = new List(); + + foreach (var permission in permissions) + { + accounts.Add(ObjectUtils.FillObjectFromDataReader(DataProvider.GetExchangeAccountByAccountName(org.Id, permission.Account))); + } + + orgProxy.SetDriveMapsTargetingFilter(org.OrganizationId, accounts.ToArray(), folderName); + } + catch (Exception ex) + { + result.AddError("ENTERPRISE_STORAGE_SET_MAPPED_DRIVE_TARGETING_FILTER", ex); + } + finally + { + if (!result.IsSuccess) + { + TaskManager.CompleteResultTask(result); + } + else + { + TaskManager.CompleteResultTask(); + } + } + + return result; + } + + private static ResultObject DeleteMappedDrivesGPO(int itemId) + { + ResultObject result = TaskManager.StartResultTask("ENTERPRISE_STORAGE", "DELETE_MAPPED_DRIVES_GPO", itemId); + + try + { + // load organization + Organization org = OrganizationController.GetOrganization(itemId); + if (org == null) + { + result.IsSuccess = false; + result.AddError("", new NullReferenceException("Organization not found")); + return result; + } + + Organizations orgProxy = OrganizationController.GetOrganizationProxy(org.ServiceId); + + orgProxy.DeleteMappedDrivesGPO(org.OrganizationId); + } + catch (Exception ex) + { + result.AddError("ENTERPRISE_STORAGE_DELETE_MAPPED_DRIVES_GPO", ex); + } + finally + { + if (!result.IsSuccess) + { + TaskManager.CompleteResultTask(result); + } + else + { + TaskManager.CompleteResultTask(); + } + } + + return result; + } + + #endregion } } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esEnterpriseStorage.asmx.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esEnterpriseStorage.asmx.cs index 19e58d80..8f81ab72 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esEnterpriseStorage.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer/esEnterpriseStorage.asmx.cs @@ -174,5 +174,39 @@ namespace WebsitePanel.EnterpriseServer } #endregion + + #region Drive Mapping + + [WebMethod] + public ResultObject CreateMappedDrive(int packageId, int itemId, string driveLetter, string labelAs, string folderName) + { + return EnterpriseStorageController.CreateMappedDrive(packageId, itemId, driveLetter, labelAs, folderName); + } + + [WebMethod] + public ResultObject DeleteMappedDrive(int itemId, string driveLetter) + { + return EnterpriseStorageController.DeleteMappedDrive(itemId, driveLetter); + } + + [WebMethod] + public MappedDrivesPaged GetDriveMapsPaged(int itemId, string filterValue, string sortColumn, int startRow, int maximumRows) + { + return EnterpriseStorageController.GetDriveMapsPaged(itemId, filterValue, sortColumn, startRow, maximumRows); + } + + [WebMethod] + public string[] GetUsedDriveLetters(int itemId) + { + return EnterpriseStorageController.GetUsedDriveLetters(itemId); + } + + [WebMethod] + public SystemFile[] GetNotMappedEnterpriseFolders(int itemId) + { + return EnterpriseStorageController.GetNotMappedEnterpriseFolders(itemId); + } + + #endregion } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/Errors.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/Errors.cs index ddc514cb..4559255b 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/Errors.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/Errors.cs @@ -32,5 +32,6 @@ namespace WebsitePanel.Providers.HostedSolution { public const int OK = 0; public const int AD_OBJECT_ALREADY_EXISTS = -1; + public const int MAPPED_DRIVE_ALREADY_EXISTS = -2; } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs index ae4a233b..829684c2 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/HostedSolution/IOrganization.cs @@ -26,6 +26,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using WebsitePanel.Providers.OS; using WebsitePanel.Providers.ResultObjects; namespace WebsitePanel.Providers.HostedSolution @@ -78,5 +79,17 @@ namespace WebsitePanel.Providers.HostedSolution string GetSamAccountNameByUserPrincipalName(string organizationId, string userPrincipalName); bool DoesSamAccountNameExist(string accountName); + + MappedDrive[] GetDriveMaps(string organizationId); + + int CreateMappedDrive(string organizationId, string drive, string labelAs, string path); + + void DeleteMappedDrive(string organizationId, string drive); + + void DeleteMappedDriveByPath(string organizationId, string path); + + void DeleteMappedDrivesGPO(string organizationId); + + void SetDriveMapsTargetingFilter(string organizationId, ExchangeAccount[] accounts, string folderName); } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrive.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrive.cs new file mode 100644 index 00000000..2a34a2d0 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrive.cs @@ -0,0 +1,80 @@ +// Copyright (c) 2014, 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. + +using System; + +namespace WebsitePanel.Providers.OS +{ + /// + /// Summary description for MappedDrive. + /// + [Serializable] + public class MappedDrive + { + private string path; + private string labelAs; + private string driveLetter; + private SystemFile folder; + + public MappedDrive() + { + } + + public MappedDrive(string path, string labelAs, string driveLetter) + { + this.Path = path; + this.LabelAs = labelAs; + this.DriveLetter = driveLetter; + SystemFile folder = null; + } + + public string Path + { + get { return this.path; } + set { this.path = value; } + } + + public string LabelAs + { + get { return this.labelAs; } + set { this.labelAs = value; } + } + + public string DriveLetter + { + get { return this.driveLetter; } + set { this.driveLetter = value; } + } + + public SystemFile Folder + { + get { return this.folder; } + set { this.folder = value; } + } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrivesPaged.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrivesPaged.cs new file mode 100644 index 00000000..35a0603d --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/MappedDrivesPaged.cs @@ -0,0 +1,20 @@ +namespace WebsitePanel.Providers.OS +{ + public class MappedDrivesPaged + { + int recordsCount; + MappedDrive[] pageItems; + + public int RecordsCount + { + get { return this.recordsCount; } + set { this.recordsCount = value; } + } + + public MappedDrive[] PageItems + { + get { return this.pageItems; } + set { this.pageItems = value; } + } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/SystemFile.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/SystemFile.cs index b7ba39ce..7ec99ac7 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/SystemFile.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/OS/SystemFile.cs @@ -49,6 +49,7 @@ namespace WebsitePanel.Providers.OS private int fsrmQuotaMB; private int frsmQuotaGB; private QuotaType fsrmQuotaType = QuotaType.Soft; + private string driveLetter; public SystemFile() { @@ -142,5 +143,11 @@ namespace WebsitePanel.Providers.OS get { return this.url; } set { this.url = value; } } + + public string DriveLetter + { + get { return this.driveLetter; } + set { this.driveLetter = value; } + } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj index 6a3141a3..2ab48c12 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj @@ -117,6 +117,8 @@ + + diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs index 0781138d..f2faeb9c 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.HostedSolution/OrganizationProvider.cs @@ -27,17 +27,35 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; +using System.IO; +using System.Xml; +using System.Linq; +using System.Text; +using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.DirectoryServices; using System.Globalization; -using System.Text; + +using System.Management.Automation; +using System.Management.Automation.Runspaces; + using WebsitePanel.Providers.Common; using WebsitePanel.Providers.ResultObjects; +using WebsitePanel.Providers.OS; namespace WebsitePanel.Providers.HostedSolution { public class OrganizationProvider : HostingServiceProviderBase, IOrganization { + #region Constants + + private const string GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE = @"\\{0}\SYSVOL\{0}\Policies\{1}\User\Preferences\Drives"; + private const string DRIVES_CLSID = "{8FDDCC1A-0C3C-43cd-A6B4-71A6DF20DA8C}"; + private const string DRIVE_CLSID = "{935D1B74-9CB8-4e3c-9914-7DD559B7A417}"; + + #endregion + #region Properties private string RootOU @@ -61,6 +79,36 @@ namespace WebsitePanel.Providers.HostedSolution #region Helpers + private string GetObjectTargetAccountName(string accountName, string domain) + { + string part = domain.Split('.')[0].ToUpperInvariant(); + + return string.Format("{0}\\{1}", part, accountName); + } + + private string GetOrganizationTargetPath(string organizationId) + { + StringBuilder sb = new StringBuilder(); + // append provider + AppendOUPath(sb, organizationId); + AppendOUPath(sb, RootOU); + AppendDomainPath(sb, RootDomain); + + return sb.ToString(); + } + + private string GetObjectTargetPath(string organizationId, string objName) + { + StringBuilder sb = new StringBuilder(); + // append provider + AppendCNPath(sb, objName); + AppendOUPath(sb, organizationId); + AppendOUPath(sb, RootOU); + AppendDomainPath(sb, RootDomain); + + return sb.ToString(); + } + private string GetOrganizationPath(string organizationId) { StringBuilder sb = new StringBuilder(); @@ -1097,6 +1145,702 @@ namespace WebsitePanel.Providers.HostedSolution #endregion + #region Drive Mapping + + public MappedDrive[] GetDriveMaps(string organizationId) + { + return GetDriveMapsInternal(organizationId); + } + + internal MappedDrive[] GetDriveMapsInternal(string organizationId) + { + HostedSolutionLog.LogStart("GetDriveMapsInternal"); + HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId); + + if (string.IsNullOrEmpty(organizationId)) + throw new ArgumentNullException("organizationId"); + + string gpoId; + + if (!CheckMappedDriveGpoExists(organizationId, out gpoId)) + { + CreateAndLinkMappedDrivesGPO(organizationId, out gpoId); + } + + ArrayList items = new ArrayList(); + + if (!string.IsNullOrEmpty(gpoId)) + { + string path = string.Format("{0}\\{1}", + string.Format(GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE, RootDomain, gpoId), + "Drives.xml"); + + // open xml document + XmlDocument xml = new XmlDocument(); + xml.Load(path); + + HostedSolutionLog.LogEnd("GetDriveMapsInternal"); + + return GetDrivesFromXML(xml, items); + } + + HostedSolutionLog.LogEnd("GetDriveMapsInternal"); + + return (MappedDrive[])items.ToArray(typeof(MappedDrive)); + } + + public int CreateMappedDrive(string organizationId, string drive, string labelAs, string path) + { + return CreateMappedDriveInternal(organizationId, drive, labelAs, path); + } + + internal int CreateMappedDriveInternal(string organizationId, string drive, string labelAs, string path) + { + HostedSolutionLog.LogStart("CreateMappedDriveInternal"); + HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId); + HostedSolutionLog.DebugInfo("driveLetter : {0}:", drive); + + if (string.IsNullOrEmpty(organizationId)) + throw new ArgumentNullException("organizationId"); + + if (string.IsNullOrEmpty(drive)) + throw new ArgumentNullException("driveLetter"); + + string gpoId; + + if (!CheckMappedDriveGpoExists(organizationId, out gpoId)) + { + CreateAndLinkMappedDrivesGPO(organizationId, out gpoId); + } + + if (CheckMappedDriveExists(organizationId, path)) + { + return Errors.MAPPED_DRIVE_ALREADY_EXISTS; + } + + if (!string.IsNullOrEmpty(gpoId)) + { + string drivesXmlPath = string.Format("{0}\\{1}", + string.Format(GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE, RootDomain, gpoId), + "Drives.xml"); + // open xml document + XmlDocument xml = new XmlDocument(); + xml.Load(drivesXmlPath); + + XmlNode drivesNode = xml.SelectSingleNode("(/*)"); + XmlNode driveNode = CreateDriveNode(xml, drive, labelAs, path); + + drivesNode.AppendChild(driveNode); + + xml.Save(drivesXmlPath); + } + + HostedSolutionLog.LogEnd("CreateMappedDriveInternal"); + + return Errors.OK; + } + + public void DeleteMappedDriveByPath(string organizationId, string path) + { + DeleteMappedDriveByPathInternal(organizationId, path); + } + + internal void DeleteMappedDriveByPathInternal(string organizationId, string path) + { + MappedDrive drive = GetDriveMaps(organizationId).Where(x => x.Path == path).FirstOrDefault(); + + if (drive != null) + { + DeleteMappedDriveInternal(organizationId, drive.DriveLetter); + } + } + + public void DeleteMappedDrive(string organizationId, string drive) + { + DeleteMappedDriveInternal(organizationId, drive); + } + + internal void DeleteMappedDriveInternal(string organizationId, string drive) + { + HostedSolutionLog.LogStart("DeleteMappedDriveInternal"); + HostedSolutionLog.DebugInfo("driveLetter : {0}:", drive); + HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId); + + if (string.IsNullOrEmpty(organizationId)) + throw new ArgumentNullException("organizationId"); + + if (string.IsNullOrEmpty(drive)) + throw new ArgumentNullException("driveLetter"); + + string gpoId; + + if (!CheckMappedDriveGpoExists(organizationId, out gpoId)) + { + CreateAndLinkMappedDrivesGPO(organizationId, out gpoId); + } + + if (!string.IsNullOrEmpty(gpoId)) + { + string path = string.Format("{0}\\{1}", + string.Format(GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE, RootDomain, gpoId), + "Drives.xml"); + + // open xml document + XmlDocument xml = new XmlDocument(); + xml.Load(path); + + XmlNode x = xml.SelectSingleNode(string.Format("/Drives/Drive[@name='{0}:']", drive)); + if (x != null) + { + x.ParentNode.RemoveChild(x); + } + + xml.Save(path); + } + + HostedSolutionLog.LogEnd("DeleteMappedDriveInternal"); + } + + public void DeleteMappedDrivesGPO(string organizationId) + { + DeleteMappedDrivesGPOInternal(organizationId); + } + + internal void DeleteMappedDrivesGPOInternal(string organizationId) + { + HostedSolutionLog.LogStart("DeleteMappedDrivesGPOInternal"); + HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId); + + Runspace runSpace = null; + + try + { + runSpace = OpenRunspace(); + + ImportGroupPolicyMolude(runSpace); + + string gpoName = string.Format("{0}-mapped-drives", organizationId); + + //create new gpo + Command cmd = new Command("Remove-GPO"); + cmd.Parameters.Add("Name", gpoName); + + ExecuteShellCommand(runSpace, cmd); + } + catch (Exception ex) + { + CloseRunspace(runSpace); + } + finally + { + CloseRunspace(runSpace); + + HostedSolutionLog.LogEnd("DeleteMappedDrivesGPOInternal"); + } + } + + public void SetDriveMapsTargetingFilter(string organizationId, ExchangeAccount[] accounts, string folderName) + { + SetDriveMapsTargetingFilterInternal(organizationId, accounts, folderName); + } + + internal void SetDriveMapsTargetingFilterInternal(string organizationId, ExchangeAccount[] accounts, string folderName) + { + HostedSolutionLog.LogStart("SetDriveMapsTargetingFilterInternal"); + HostedSolutionLog.DebugInfo("organizationId : {0}", organizationId); + HostedSolutionLog.DebugInfo("folderName : {0}", folderName); + + if (string.IsNullOrEmpty(organizationId)) + throw new ArgumentNullException("organizationId"); + + if (string.IsNullOrEmpty(folderName)) + throw new ArgumentNullException("folderName"); + + Runspace runSpace = null; + + try + { + runSpace = OpenRunspace(); + + //import grouppolicy module + ImportGroupPolicyMolude(runSpace); + + Dictionary sidAccountPairs = new Dictionary(); + + Command cmd; + + foreach (var account in accounts) + { + string pathObj = GetObjectTargetPath(organizationId, account.AccountName); + + if (IsGroup(account)) + { + //get group sid + cmd = new Command("Get-ADGroup"); + cmd.Parameters.Add("SearchBase", pathObj); + cmd.Parameters.Add("Filter", "*"); + + Collection result = ExecuteShellCommand(runSpace, cmd); + + if (result != null && result.Count > 0) + { + PSObject group = result[0]; + + sidAccountPairs.Add(GetPSObjectProperty(group, "SID").ToString(), account); + } + } + else + { + //get user sid + cmd = new Command("Get-ADUser"); + cmd.Parameters.Add("SearchBase", pathObj); + cmd.Parameters.Add("Filter", "*"); + + Collection result = ExecuteShellCommand(runSpace, cmd); + + if (result != null && result.Count > 0) + { + PSObject user = result[0]; + + sidAccountPairs.Add(GetPSObjectProperty(user, "SID").ToString(), account); + } + } + } + + string gpoId; + + if (!CheckMappedDriveGpoExists(organizationId, out gpoId)) + { + CreateAndLinkMappedDrivesGPO(organizationId, out gpoId); + } + + if (!string.IsNullOrEmpty(gpoId)) + { + string drivesXmlPath = string.Format("{0}\\{1}", + string.Format(GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE, RootDomain, gpoId), + "Drives.xml"); + // open xml document + XmlDocument xml = new XmlDocument(); + xml.Load(drivesXmlPath); + + XmlNodeList drives = xml.SelectNodes(string.Format("./Drives/Drive[contains(Properties/@path,'{0}')]", folderName)); + + foreach (XmlNode driveNode in drives) + { + XmlNodeList childNodes = driveNode.ChildNodes; + + if (childNodes.Count > 1) + { + //delete existing filters + driveNode.LastChild.ParentNode.RemoveChild(driveNode.LastChild); + } + + XmlNode newFiltersNode = CreateFiltersNode(xml, sidAccountPairs); + + driveNode.AppendChild(newFiltersNode); + } + + xml.Save(drivesXmlPath); + } + } + catch (Exception ex) + { + + } + finally + { + CloseRunspace(runSpace); + + HostedSolutionLog.LogEnd("SetDriveMapsTargetingFilterInternal"); + } + } + + private void CreateAndLinkMappedDrivesGPO(string organizationId, out string gpoId) + { + Runspace runSpace = null; + + try + { + runSpace = OpenRunspace(); + + ImportGroupPolicyMolude(runSpace); + + string gpoName = string.Format("{0}-mapped-drives", organizationId); + string pathOU = GetOrganizationTargetPath(organizationId); + + //create new gpo + Command cmd = new Command("New-GPO"); + cmd.Parameters.Add("Name", gpoName); + + Collection result = ExecuteShellCommand(runSpace, cmd); + + gpoId = null; + + if (result != null && result.Count > 0) + { + PSObject gpo = result[0]; + //get gpo id + gpoId = ((Guid)GetPSObjectProperty(gpo, "Id")).ToString("B"); + + } + + //create gpo link + cmd = new Command("New-GPLink"); + cmd.Parameters.Add("Name", gpoName); + cmd.Parameters.Add("Target", pathOU); + + ExecuteShellCommand(runSpace, cmd); + + //create empty drives.xml file for for gpo drives mapping + CreateDrivesXmlEmpty(string.Format(GROUP_POLICY_MAPPED_DRIVES_FILE_PATH_TEMPLATE, RootDomain, gpoId), "Drives.xml"); + } + catch (Exception ex) + { + gpoId = null; + CloseRunspace(runSpace); + } + finally + { + CloseRunspace(runSpace); + } + } + + private bool CheckMappedDriveGpoExists(string organizationId, out string gpoId) + { + Runspace runSpace = null; + + try + { + runSpace = OpenRunspace(); + + ImportGroupPolicyMolude(runSpace); + + string gpoName = string.Format("{0}-mapped-drives", organizationId); + + Command cmd = new Command("Get-GPO"); + cmd.Parameters.Add("Name", gpoName); + + Collection result = ExecuteShellCommand(runSpace, cmd); + + gpoId = null; + + if (result != null && result.Count > 0) + { + PSObject gpo = result[0]; + gpoId = ((Guid)GetPSObjectProperty(gpo, "Id")).ToString("B"); + } + } + finally + { + CloseRunspace(runSpace); + } + + return string.IsNullOrEmpty(gpoId) ? false : true; + } + + private bool CheckMappedDriveExists(string organizationId, string path) + { + bool exists = false; + + MappedDrive[] drives = GetDriveMapsInternal(organizationId); + + foreach (var item in drives) + { + if (item.Path == path) + { + exists = true; + break; + } + } + + return exists; + } + + #region Drive Mapping Helpers + + private void ImportGroupPolicyMolude(Runspace runSpace) + { + Command cmd = new Command("Import-Module"); + cmd.Parameters.Add("Name", "grouppolicy"); + + ExecuteShellCommand(runSpace, cmd); + } + + private void CreateDrivesXmlEmpty(string path, string fileName) + { + DirectoryInfo drivesDirectory = new DirectoryInfo(path); + + if (!drivesDirectory.Exists) + { + drivesDirectory.Create(); + } + + XmlDocument doc = new XmlDocument(); + + XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null); + doc.AppendChild(docNode); + + XmlNode drivesNode = doc.CreateElement("Drives"); + + XmlAttribute drivesAttribute = doc.CreateAttribute("clsid"); + drivesAttribute.Value = DRIVES_CLSID; + drivesNode.Attributes.Append(drivesAttribute); + + doc.AppendChild(drivesNode); + + doc.Save(string.Format("{0}\\{1}", path, fileName)); + } + + private XmlNode CreateDriveNode(XmlDocument xml, string drive, string labelAs, string path) + { + XmlNode driveNode = xml.CreateElement("Drive"); + XmlNode propertiesNode = xml.CreateElement("Properties");; + + XmlAttribute clsidAttr = xml.CreateAttribute("clsid"); + XmlAttribute nameAttr = xml.CreateAttribute("name"); + XmlAttribute statusAttr = xml.CreateAttribute("status"); + XmlAttribute imageAttr = xml.CreateAttribute("image"); + XmlAttribute changedAttr = xml.CreateAttribute("changed"); + XmlAttribute uidAttr = xml.CreateAttribute("uid"); + XmlAttribute bypassErrorsAttr = xml.CreateAttribute("bypassErrors"); + + XmlAttribute actionPropAttr = xml.CreateAttribute("action"); + XmlAttribute thisDrivePropAttr = xml.CreateAttribute("thisDrive"); + XmlAttribute allDrivesPropAttr = xml.CreateAttribute("allDrives"); + XmlAttribute userNamePropAttr = xml.CreateAttribute("userName"); + XmlAttribute pathPropAttr = xml.CreateAttribute("path"); + XmlAttribute labelPropAttr = xml.CreateAttribute("label"); + XmlAttribute persistentPropAttr = xml.CreateAttribute("persistent"); + XmlAttribute useLetterPropAttr = xml.CreateAttribute("useLetter"); + XmlAttribute letterPropAttr = xml.CreateAttribute("letter"); + + clsidAttr.Value = DRIVE_CLSID; + nameAttr.Value = string.Format("{0}:", drive); + statusAttr.Value = string.Format("{0}:", drive); + imageAttr.Value = (1).ToString(); + changedAttr.Value = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"); + uidAttr.Value = Guid.NewGuid().ToString("B"); + bypassErrorsAttr.Value = (1).ToString(); + + actionPropAttr.Value = "R"; + thisDrivePropAttr.Value = "NOCHANGE"; + allDrivesPropAttr.Value = "NOCHANGE"; + userNamePropAttr.Value = string.Empty; + pathPropAttr.Value = path; + labelPropAttr.Value = labelAs; + persistentPropAttr.Value = (1).ToString(); + useLetterPropAttr.Value = (1).ToString(); + letterPropAttr.Value = drive; + + driveNode.Attributes.Append(clsidAttr); + driveNode.Attributes.Append(nameAttr); + driveNode.Attributes.Append(statusAttr); + driveNode.Attributes.Append(imageAttr); + driveNode.Attributes.Append(changedAttr); + driveNode.Attributes.Append(uidAttr); + driveNode.Attributes.Append(bypassErrorsAttr); + + propertiesNode.Attributes.Append(actionPropAttr); + propertiesNode.Attributes.Append(thisDrivePropAttr); + propertiesNode.Attributes.Append(allDrivesPropAttr); + propertiesNode.Attributes.Append(userNamePropAttr); + propertiesNode.Attributes.Append(pathPropAttr); + propertiesNode.Attributes.Append(labelPropAttr); + propertiesNode.Attributes.Append(persistentPropAttr); + propertiesNode.Attributes.Append(useLetterPropAttr); + propertiesNode.Attributes.Append(letterPropAttr); + + driveNode.AppendChild(propertiesNode); + + return driveNode; + } + + private XmlNode CreateFiltersNode(XmlDocument xml, Dictionary accounts) + { + XmlNode filtersNode = xml.CreateElement("Filters"); + + foreach (var pair in accounts) + { + XmlAttribute boolAttr = xml.CreateAttribute("bool"); + XmlAttribute notAttr = xml.CreateAttribute("not"); + XmlAttribute userContextAttr = xml.CreateAttribute("userContext"); + XmlAttribute primaryGroupAttr = xml.CreateAttribute("primaryGroup"); + XmlAttribute localGroupAttr = xml.CreateAttribute("localGroup"); + XmlAttribute nameAttr = xml.CreateAttribute("name"); + XmlAttribute sidAttr = xml.CreateAttribute("sid"); + + boolAttr.Value = "AND"; + notAttr.Value = (0).ToString(); + userContextAttr.Value = (1).ToString(); + primaryGroupAttr.Value = (0).ToString(); + localGroupAttr.Value = (0).ToString(); + + if (IsGroup(pair.Value)) + { + XmlNode filterGroupNode = xml.CreateElement("FilterGroup"); + + nameAttr.Value = GetObjectTargetAccountName(pair.Value.AccountName, RootDomain); + sidAttr.Value = pair.Key; + + filterGroupNode.Attributes.Append(boolAttr); + filterGroupNode.Attributes.Append(notAttr); + filterGroupNode.Attributes.Append(nameAttr); + filterGroupNode.Attributes.Append(sidAttr); + filterGroupNode.Attributes.Append(userContextAttr); + filterGroupNode.Attributes.Append(primaryGroupAttr); + filterGroupNode.Attributes.Append(localGroupAttr); + + filtersNode.AppendChild(filterGroupNode); + } + else + { + XmlNode filterUserNode = xml.CreateElement("FilterUser"); + + nameAttr.Value = GetObjectTargetAccountName(pair.Value.AccountName, RootDomain); + sidAttr.Value = pair.Key; + + filterUserNode.Attributes.Append(boolAttr); + filterUserNode.Attributes.Append(notAttr); + filterUserNode.Attributes.Append(nameAttr); + filterUserNode.Attributes.Append(sidAttr); + + filtersNode.AppendChild(filterUserNode); + } + } + + return filtersNode; + } + + private MappedDrive[] GetDrivesFromXML(XmlDocument xml, ArrayList items) + { + XmlNodeList drives = xml.SelectNodes("./Drives/Drive"); + + foreach (XmlNode driveNode in drives) + { + XmlNode props = driveNode.ChildNodes[0]; + + MappedDrive item = new MappedDrive(props.Attributes["path"].Value, + props.Attributes["label"].Value, + props.Attributes["letter"].Value); + items.Add(item); + } + + return (MappedDrive[])items.ToArray(typeof(MappedDrive)); + } + + private bool IsGroup(ExchangeAccount account) + { + return (account.AccountType == ExchangeAccountType.SecurityGroup || account.AccountType == ExchangeAccountType.DefaultSecurityGroup); + } + + #endregion + + #endregion + + #region PowerShell integration + + private static RunspaceConfiguration runspaceConfiguration = null; + + internal virtual Runspace OpenRunspace() + { + HostedSolutionLog.LogStart("OpenRunspace"); + + if (runspaceConfiguration == null) + { + runspaceConfiguration = RunspaceConfiguration.Create(); + } + Runspace runSpace = RunspaceFactory.CreateRunspace(runspaceConfiguration); + // + runSpace.Open(); + // + runSpace.SessionStateProxy.SetVariable("ConfirmPreference", "none"); + HostedSolutionLog.LogEnd("OpenRunspace"); + return runSpace; + } + + internal void CloseRunspace(Runspace runspace) + { + try + { + if (runspace != null && runspace.RunspaceStateInfo.State == RunspaceState.Opened) + { + runspace.Close(); + } + } + catch (Exception ex) + { + HostedSolutionLog.LogError("Runspace error", ex); + } + } + + internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd) + { + return ExecuteShellCommand(runSpace, cmd, false); + } + + internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController) + { + object[] errors; + return ExecuteShellCommand(runSpace, cmd, useDomainController, out errors); + } + + internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, out object[] errors) + { + return ExecuteShellCommand(runSpace, cmd, true, out errors); + } + + internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController, out object[] errors) + { + HostedSolutionLog.LogStart("ExecuteShellCommand"); + List errorList = new List(); + + if (useDomainController) + { + CommandParameter dc = new CommandParameter("DomainController", PrimaryDomainController); + if (!cmd.Parameters.Contains(dc)) + { + cmd.Parameters.Add(dc); + } + } + + HostedSolutionLog.DebugCommand(cmd); + Collection results = null; + // Create a pipeline + Pipeline pipeLine = runSpace.CreatePipeline(); + using (pipeLine) + { + // Add the command + pipeLine.Commands.Add(cmd); + // Execute the pipeline and save the objects returned. + results = pipeLine.Invoke(); + + // Log out any errors in the pipeline execution + // NOTE: These errors are NOT thrown as exceptions! + // Be sure to check this to ensure that no errors + // happened while executing the command. + if (pipeLine.Error != null && pipeLine.Error.Count > 0) + { + foreach (object item in pipeLine.Error.ReadToEnd()) + { + errorList.Add(item); + string errorMessage = string.Format("Invoke error: {0}", item); + HostedSolutionLog.LogWarning(errorMessage); + } + } + } + pipeLine = null; + errors = errorList.ToArray(); + HostedSolutionLog.LogEnd("ExecuteShellCommand"); + return results; + } + + internal object GetPSObjectProperty(PSObject obj, string name) + { + return obj.Members[name].Value; + } + + #endregion + public override bool IsInstalled() { return Environment.UserDomainName != Environment.MachineName; diff --git a/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs b/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs index ec17ae8c..75847ebd 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server.Client/OrganizationProxy.cs @@ -50,6 +50,7 @@ namespace WebsitePanel.Providers.HostedSolution using WebsitePanel.Providers.Common; using WebsitePanel.Providers.ResultObjects; + using WebsitePanel.Providers.OS; @@ -105,6 +106,18 @@ namespace WebsitePanel.Providers.HostedSolution private System.Threading.SendOrPostCallback DoesSamAccountNameExistOperationCompleted; + private System.Threading.SendOrPostCallback GetDriveMapsOperationCompleted; + + private System.Threading.SendOrPostCallback CreateMappedDriveOperationCompleted; + + private System.Threading.SendOrPostCallback DeleteMappedDriveOperationCompleted; + + private System.Threading.SendOrPostCallback DeleteMappedDriveByPathOperationCompleted; + + private System.Threading.SendOrPostCallback DeleteMappedDrivesGPOOperationCompleted; + + private System.Threading.SendOrPostCallback SetDriveMapsTargetingFilterOperationCompleted; + /// public Organizations() { @@ -171,6 +184,24 @@ namespace WebsitePanel.Providers.HostedSolution /// public event DoesSamAccountNameExistCompletedEventHandler DoesSamAccountNameExistCompleted; + /// + public event GetDriveMapsCompletedEventHandler GetDriveMapsCompleted; + + /// + public event CreateMappedDriveCompletedEventHandler CreateMappedDriveCompleted; + + /// + public event DeleteMappedDriveCompletedEventHandler DeleteMappedDriveCompleted; + + /// + public event DeleteMappedDriveByPathCompletedEventHandler DeleteMappedDriveByPathCompleted; + + /// + public event DeleteMappedDrivesGPOCompletedEventHandler DeleteMappedDrivesGPOCompleted; + + /// + public event SetDriveMapsTargetingFilterCompletedEventHandler SetDriveMapsTargetingFilterCompleted; + /// [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/OrganizationExists", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] @@ -1414,6 +1445,319 @@ namespace WebsitePanel.Providers.HostedSolution } } + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/GetDriveMaps", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public MappedDrive[] GetDriveMaps(string organizationId) + { + object[] results = this.Invoke("GetDriveMaps", new object[] { + organizationId}); + return ((MappedDrive[])(results[0])); + } + + /// + public System.IAsyncResult BeginGetDriveMaps(string organizationId, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("GetDriveMaps", new object[] { + organizationId}, callback, asyncState); + } + + /// + public MappedDrive[] EndGetDriveMaps(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((MappedDrive[])(results[0])); + } + + /// + public void GetDriveMapsAsync(string organizationId) + { + this.GetDriveMapsAsync(organizationId, null); + } + + /// + public void GetDriveMapsAsync(string organizationId, object userState) + { + if ((this.GetDriveMapsOperationCompleted == null)) + { + this.GetDriveMapsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnGetDriveMapsOperationCompleted); + } + this.InvokeAsync("GetDriveMaps", new object[] { + organizationId}, this.GetDriveMapsOperationCompleted, userState); + } + + private void OnGetDriveMapsOperationCompleted(object arg) + { + if ((this.GetDriveMapsCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.GetDriveMapsCompleted(this, new GetDriveMapsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/CreateMappedDrive", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public int CreateMappedDrive(string organizationId, string drive, string labelAs, string path) + { + object[] results = this.Invoke("CreateMappedDrive", new object[] { + organizationId, + drive, + labelAs, + path}); + return ((int)(results[0])); + } + + /// + public System.IAsyncResult BeginCreateMappedDrive(string organizationId, string drive, string labelAs, string path, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("CreateMappedDrive", new object[] { + organizationId, + drive, + labelAs, + path}, callback, asyncState); + } + + /// + public int EndCreateMappedDrive(System.IAsyncResult asyncResult) + { + object[] results = this.EndInvoke(asyncResult); + return ((int)(results[0])); + } + + /// + public void CreateMappedDriveAsync(string organizationId, string drive, string labelAs, string path) + { + this.CreateMappedDriveAsync(organizationId, drive, labelAs, path, null); + } + + /// + public void CreateMappedDriveAsync(string organizationId, string drive, string labelAs, string path, object userState) + { + if ((this.CreateMappedDriveOperationCompleted == null)) + { + this.CreateMappedDriveOperationCompleted = new System.Threading.SendOrPostCallback(this.OnCreateMappedDriveOperationCompleted); + } + this.InvokeAsync("CreateMappedDrive", new object[] { + organizationId, + drive, + labelAs, + path}, this.CreateMappedDriveOperationCompleted, userState); + } + + private void OnCreateMappedDriveOperationCompleted(object arg) + { + if ((this.CreateMappedDriveCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.CreateMappedDriveCompleted(this, new CreateMappedDriveCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/DeleteMappedDrive", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public void DeleteMappedDrive(string organizationId, string drive) + { + this.Invoke("DeleteMappedDrive", new object[] { + organizationId, + drive}); + } + + /// + public System.IAsyncResult BeginDeleteMappedDrive(string organizationId, string drive, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("DeleteMappedDrive", new object[] { + organizationId, + drive}, callback, asyncState); + } + + /// + public void EndDeleteMappedDrive(System.IAsyncResult asyncResult) + { + this.EndInvoke(asyncResult); + } + + /// + public void DeleteMappedDriveAsync(string organizationId, string drive) + { + this.DeleteMappedDriveAsync(organizationId, drive, null); + } + + /// + public void DeleteMappedDriveAsync(string organizationId, string drive, object userState) + { + if ((this.DeleteMappedDriveOperationCompleted == null)) + { + this.DeleteMappedDriveOperationCompleted = new System.Threading.SendOrPostCallback(this.OnDeleteMappedDriveOperationCompleted); + } + this.InvokeAsync("DeleteMappedDrive", new object[] { + organizationId, + drive}, this.DeleteMappedDriveOperationCompleted, userState); + } + + private void OnDeleteMappedDriveOperationCompleted(object arg) + { + if ((this.DeleteMappedDriveCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.DeleteMappedDriveCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/DeleteMappedDriveByPath", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public void DeleteMappedDriveByPath(string organizationId, string path) + { + this.Invoke("DeleteMappedDriveByPath", new object[] { + organizationId, + path}); + } + + /// + public System.IAsyncResult BeginDeleteMappedDriveByPath(string organizationId, string path, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("DeleteMappedDriveByPath", new object[] { + organizationId, + path}, callback, asyncState); + } + + /// + public void EndDeleteMappedDriveByPath(System.IAsyncResult asyncResult) + { + this.EndInvoke(asyncResult); + } + + /// + public void DeleteMappedDriveByPathAsync(string organizationId, string path) + { + this.DeleteMappedDriveByPathAsync(organizationId, path, null); + } + + /// + public void DeleteMappedDriveByPathAsync(string organizationId, string path, object userState) + { + if ((this.DeleteMappedDriveByPathOperationCompleted == null)) + { + this.DeleteMappedDriveByPathOperationCompleted = new System.Threading.SendOrPostCallback(this.OnDeleteMappedDriveByPathOperationCompleted); + } + this.InvokeAsync("DeleteMappedDriveByPath", new object[] { + organizationId, + path}, this.DeleteMappedDriveByPathOperationCompleted, userState); + } + + private void OnDeleteMappedDriveByPathOperationCompleted(object arg) + { + if ((this.DeleteMappedDriveByPathCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.DeleteMappedDriveByPathCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/DeleteMappedDrivesGPO", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public void DeleteMappedDrivesGPO(string organizationId) + { + this.Invoke("DeleteMappedDrivesGPO", new object[] { + organizationId}); + } + + /// + public System.IAsyncResult BeginDeleteMappedDrivesGPO(string organizationId, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("DeleteMappedDrivesGPO", new object[] { + organizationId}, callback, asyncState); + } + + /// + public void EndDeleteMappedDrivesGPO(System.IAsyncResult asyncResult) + { + this.EndInvoke(asyncResult); + } + + /// + public void DeleteMappedDrivesGPOAsync(string organizationId) + { + this.DeleteMappedDrivesGPOAsync(organizationId, null); + } + + /// + public void DeleteMappedDrivesGPOAsync(string organizationId, object userState) + { + if ((this.DeleteMappedDrivesGPOOperationCompleted == null)) + { + this.DeleteMappedDrivesGPOOperationCompleted = new System.Threading.SendOrPostCallback(this.OnDeleteMappedDrivesGPOOperationCompleted); + } + this.InvokeAsync("DeleteMappedDrivesGPO", new object[] { + organizationId}, this.DeleteMappedDrivesGPOOperationCompleted, userState); + } + + private void OnDeleteMappedDrivesGPOOperationCompleted(object arg) + { + if ((this.DeleteMappedDrivesGPOCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.DeleteMappedDrivesGPOCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")] + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/SetDriveMapsTargetingFilter", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public void SetDriveMapsTargetingFilter(string organizationId, ExchangeAccount[] accounts, string folderName) + { + this.Invoke("SetDriveMapsTargetingFilter", new object[] { + organizationId, + accounts, + folderName}); + } + + /// + public System.IAsyncResult BeginSetDriveMapsTargetingFilter(string organizationId, ExchangeAccount[] accounts, string folderName, System.AsyncCallback callback, object asyncState) + { + return this.BeginInvoke("SetDriveMapsTargetingFilter", new object[] { + organizationId, + accounts, + folderName}, callback, asyncState); + } + + /// + public void EndSetDriveMapsTargetingFilter(System.IAsyncResult asyncResult) + { + this.EndInvoke(asyncResult); + } + + /// + public void SetDriveMapsTargetingFilterAsync(string organizationId, ExchangeAccount[] accounts, string folderName) + { + this.SetDriveMapsTargetingFilterAsync(organizationId, accounts, folderName, null); + } + + /// + public void SetDriveMapsTargetingFilterAsync(string organizationId, ExchangeAccount[] accounts, string folderName, object userState) + { + if ((this.SetDriveMapsTargetingFilterOperationCompleted == null)) + { + this.SetDriveMapsTargetingFilterOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSetDriveMapsTargetingFilterOperationCompleted); + } + this.InvokeAsync("SetDriveMapsTargetingFilter", new object[] { + organizationId, + accounts, + folderName}, this.SetDriveMapsTargetingFilterOperationCompleted, userState); + } + + private void OnSetDriveMapsTargetingFilterOperationCompleted(object arg) + { + if ((this.SetDriveMapsTargetingFilterCompleted != null)) + { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.SetDriveMapsTargetingFilterCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// public new void CancelAsync(object userState) { @@ -1734,4 +2078,80 @@ namespace WebsitePanel.Providers.HostedSolution } } } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void GetDriveMapsCompletedEventHandler(object sender, GetDriveMapsCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class GetDriveMapsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal GetDriveMapsCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) + { + this.results = results; + } + + /// + public MappedDrive[] Result + { + get + { + this.RaiseExceptionIfNecessary(); + return ((MappedDrive[])(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void CreateMappedDriveCompletedEventHandler(object sender, CreateMappedDriveCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class CreateMappedDriveCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs + { + + private object[] results; + + internal CreateMappedDriveCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) + { + this.results = results; + } + + /// + public int Result + { + get + { + this.RaiseExceptionIfNecessary(); + return ((int)(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void DeleteMappedDriveCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void DeleteMappedDriveByPathCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void DeleteMappedDrivesGPOCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")] + public delegate void SetDriveMapsTargetingFilterCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); } diff --git a/WebsitePanel/Sources/WebsitePanel.Server/Organizations.asmx.cs b/WebsitePanel/Sources/WebsitePanel.Server/Organizations.asmx.cs index 4aa7b3a4..7fa769bd 100644 --- a/WebsitePanel/Sources/WebsitePanel.Server/Organizations.asmx.cs +++ b/WebsitePanel/Sources/WebsitePanel.Server/Organizations.asmx.cs @@ -32,6 +32,7 @@ using System.Web.Services; using System.Web.Services.Protocols; using WebsitePanel.Providers; using WebsitePanel.Providers.HostedSolution; +using WebsitePanel.Providers.OS; using WebsitePanel.Providers.ResultObjects; using WebsitePanel.Server.Utils; @@ -205,5 +206,40 @@ namespace WebsitePanel.Server return Organization.DoesSamAccountNameExist(accountName); } + [WebMethod, SoapHeader("settings")] + public MappedDrive[] GetDriveMaps(string organizationId) + { + return Organization.GetDriveMaps(organizationId); + } + + [WebMethod, SoapHeader("settings")] + public int CreateMappedDrive(string organizationId, string drive, string labelAs, string path) + { + return Organization.CreateMappedDrive(organizationId, drive, labelAs, path); + } + + [WebMethod, SoapHeader("settings")] + public void DeleteMappedDrive(string organizationId, string drive) + { + Organization.DeleteMappedDrive(organizationId, drive); + } + + [WebMethod, SoapHeader("settings")] + public void DeleteMappedDriveByPath(string organizationId, string path) + { + Organization.DeleteMappedDriveByPath(organizationId, path); + } + + [WebMethod, SoapHeader("settings")] + public void DeleteMappedDrivesGPO(string organizationId) + { + Organization.DeleteMappedDrivesGPO(organizationId); + } + + [WebMethod, SoapHeader("settings")] + public void SetDriveMapsTargetingFilter(string organizationId, ExchangeAccount[] accounts, string folderName) + { + Organization.SetDriveMapsTargetingFilter(organizationId, accounts, folderName); + } } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/WebsitePanel_Modules.config b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/WebsitePanel_Modules.config index 361d6b7b..7d629900 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/WebsitePanel_Modules.config +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Data/WebsitePanel_Modules.config @@ -556,6 +556,8 @@ + + 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 77c3ab4e..8a72260c 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_GlobalResources/WebsitePanel_SharedResources.ascx.resx @@ -5452,4 +5452,7 @@ Archiving Mailboxes per Organization + + Use Drive Maps + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Icons.skin b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Icons.skin index 2e2c3967..9eac89de 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Icons.skin +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Icons.skin @@ -94,4 +94,5 @@ Default skin template. The following skins are provided as examples only. <%-- Enterprise Storage Icons --%> - \ No newline at end of file + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/net_drive16.png b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/net_drive16.png new file mode 100644 index 00000000..3a62b557 Binary files /dev/null and b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/net_drive16.png differ diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/net_drive48.png b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/net_drive48.png new file mode 100644 index 00000000..94a926d5 Binary files /dev/null and b/WebsitePanel/Sources/WebsitePanel.WebPortal/App_Themes/Default/Images/Exchange/net_drive48.png differ diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/OrganizationMenu.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/OrganizationMenu.ascx.resx index d80cb8ce..7473ebba 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/OrganizationMenu.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/App_LocalResources/OrganizationMenu.ascx.resx @@ -228,4 +228,7 @@ Retention Policy Tag + + Drive Maps + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Helpers/EnterpriseStorageHelper.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Helpers/EnterpriseStorageHelper.cs index fcfe1270..e8ac4a64 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Helpers/EnterpriseStorageHelper.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Helpers/EnterpriseStorageHelper.cs @@ -25,5 +25,27 @@ namespace WebsitePanel.Portal } #endregion + + #region Drive Maps + + MappedDrivesPaged mappedDrives; + + public int GetEnterpriseDriveMapsPagedCount(int itemId, string filterValue) + { + return mappedDrives.RecordsCount; + } + + public MappedDrive[] GetEnterpriseDriveMapsPaged(int itemId, string filterValue, + int maximumRows, int startRowIndex, string sortColumn) + { + filterValue = filterValue ?? string.Empty; + + mappedDrives = ES.Services.EnterpriseStorage.GetDriveMapsPaged(itemId, + filterValue, sortColumn, startRowIndex, maximumRows); + + return mappedDrives.PageItems; + } + + #endregion } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/EnterpriseStorageCreateDriveMap.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/EnterpriseStorageCreateDriveMap.ascx.resx new file mode 100644 index 00000000..cfab2940 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/EnterpriseStorageCreateDriveMap.ascx.resx @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ShowProgressDialog('Creating drive map ...'); + + + Create Drive Map + + + + + + Folder Name: * + + + Drive Maps + + + Enter Folder Name + + + * + + + Create New Drive Map + + + Label As: + + + Storage Folder: + + + * + + + valRequireFolderSize + + + Enter Folder Size + + + Select Drive Letter: + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/EnterpriseStorageDriveMaps.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/EnterpriseStorageDriveMaps.ascx.resx new file mode 100644 index 00000000..482bb752 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/EnterpriseStorageDriveMaps.ascx.resx @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Create New Drive Map + + + if(!confirm('Are you sure you want to delete selected drive map?')) return false; else ShowProgressDialog('Deleting Drive Map...'); + + + Delete + + + Delete Drive Map + + + No drive maps have been added yet. To add a new folder click "Create New Drive Map" button. + + + + + + Drive Maps + + + Drive + + + Drive Maps + + + Url + + + Label + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/EnterpriseStorageFolders.ascx.resx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/EnterpriseStorageFolders.ascx.resx index f49dd179..5724b4fb 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/EnterpriseStorageFolders.ascx.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/App_LocalResources/EnterpriseStorageFolders.ascx.resx @@ -162,4 +162,7 @@ Used Diskspace (Mb): + + Drive Map + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageCreateDriveMap.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageCreateDriveMap.ascx new file mode 100644 index 00000000..782c6530 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageCreateDriveMap.ascx @@ -0,0 +1,74 @@ +<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="EnterpriseStorageCreateDriveMap.ascx.cs" Inherits="WebsitePanel.Portal.ExchangeServer.EnterpriseStorageCreateDriveMap" %> +<%@ Register Src="../UserControls/SimpleMessageBox.ascx" TagName="SimpleMessageBox" TagPrefix="wsp" %> +<%@ Register Src="UserControls/EmailAddress.ascx" TagName="EmailAddress" TagPrefix="wsp" %> +<%@ Register Src="../UserControls/EnableAsyncTasksSupport.ascx" TagName="EnableAsyncTasksSupport" TagPrefix="wsp" %> + + + + +
+
+
+
+
+
+
+ + +
+
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+
+ +
+
+
+ +
+
+ +
+ + +
+
+
+
+
+
+ \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageCreateDriveMap.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageCreateDriveMap.ascx.cs new file mode 100644 index 00000000..8a9b9b5e --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageCreateDriveMap.ascx.cs @@ -0,0 +1,122 @@ +// Copyright (c) 2014, 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. + +using System; +using System.Web.UI.WebControls; +using WebsitePanel.EnterpriseServer; +using WebsitePanel.Providers.Common; +using WebsitePanel.Providers.HostedSolution; +using WebsitePanel.Providers.OS; + +namespace WebsitePanel.Portal.ExchangeServer +{ + public partial class EnterpriseStorageCreateDriveMap : WebsitePanelModuleBase + { + + protected void Page_Load(object sender, EventArgs e) + { + if (!IsPostBack) + { + BindLetters(); + BindFolders(); + } + + if (ddlFolders.Items.Count < 1 || ddlLetters.Items.Count < 1) + { + btnCreate.Enabled = false; + } + } + + private void BindFolders() + { + ddlFolders.DataSource = ES.Services.EnterpriseStorage.GetNotMappedEnterpriseFolders(PanelRequest.ItemID); + ddlFolders.DataTextField = "Name"; + ddlFolders.DataValueField = "Url"; + ddlFolders.DataBind(); + + if (ddlFolders.Items.Count > 0) + { + txtLabelAs.Text = ddlFolders.SelectedItem.Text; + lbFolderUrl.Text = ddlFolders.SelectedItem.Value; + } + } + + private void BindLetters() + { + //for (int i = 65; i < 91; i++) // increment from ASCII values for A-Z + for (int i = 69; i < 91; i++) // E-Z + { + ddlLetters.Items.Add(new ListItem(Convert.ToChar(i).ToString() + ":", Convert.ToChar(i).ToString()));// Add uppercase letters to possible drive letters + } + + string[] usedLetters = ES.Services.EnterpriseStorage.GetUsedDriveLetters(PanelRequest.ItemID); + + foreach (string elem in usedLetters) + { + ListItem item = new ListItem(elem + ":", elem); + if (ddlLetters.Items.Contains(item)) + { + ddlLetters.Items.Remove(item); + } + } + } + + protected void btnCreate_Click(object sender, EventArgs e) + { + if (!Page.IsValid) + return; + try + { + if (!ES.Services.EnterpriseStorage.CheckEnterpriseStorageInitialization(PanelSecurity.PackageId, PanelRequest.ItemID)) + { + ES.Services.EnterpriseStorage.CreateEnterpriseStorage(PanelSecurity.PackageId, PanelRequest.ItemID); + } + + ResultObject result = ES.Services.EnterpriseStorage.CreateMappedDrive( + PanelSecurity.PackageId, + PanelRequest.ItemID, + ddlLetters.SelectedItem.Value, + txtLabelAs.Text, + ddlFolders.SelectedItem.Text); + + if (!result.IsSuccess && result.ErrorCodes.Count > 0) + { + messageBox.ShowMessage(result, "ENTERPRISE_STORAGE_CREATE_MAPPED_DRIVE", "Enterprise Storage"); + return; + } + + Response.Redirect(EditUrl("ItemID", PanelRequest.ItemID.ToString(), "enterprisestorage_drive_maps", + "SpaceID=" + PanelSecurity.PackageId)); + } + catch (Exception ex) + { + messageBox.ShowErrorMessage("ENTERPRISE_STORAGE_CREATE_MAPPED_DRIVE", ex); + } + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageCreateDriveMap.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageCreateDriveMap.ascx.designer.cs new file mode 100644 index 00000000..e1b30731 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageCreateDriveMap.ascx.designer.cs @@ -0,0 +1,132 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WebsitePanel.Portal.ExchangeServer { + + + public partial class EnterpriseStorageCreateDriveMap { + + /// + /// asyncTasks control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.EnableAsyncTasksSupport asyncTasks; + + /// + /// imgESDM control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Image imgESDM; + + /// + /// locTitle control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locTitle; + + /// + /// messageBox control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.UserControls.SimpleMessageBox messageBox; + + /// + /// locDriveLetter control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locDriveLetter; + + /// + /// ddlLetters control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.DropDownList ddlLetters; + + /// + /// locFolder control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locFolder; + + /// + /// ddlFolders control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.DropDownList ddlFolders; + + /// + /// lbFolderUrl control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal lbFolderUrl; + + /// + /// locDriveLabel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locDriveLabel; + + /// + /// txtLabelAs control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtLabelAs; + + /// + /// btnCreate control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnCreate; + + /// + /// valSummary control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.ValidationSummary valSummary; + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageDriveMaps.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageDriveMaps.ascx new file mode 100644 index 00000000..33c6c544 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageDriveMaps.ascx @@ -0,0 +1,90 @@ +<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="EnterpriseStorageDriveMaps.ascx.cs" Inherits="WebsitePanel.Portal.ExchangeServer.EnterpriseStorageDriveMaps" %> +<%@ Register Src="../UserControls/SimpleMessageBox.ascx" TagName="SimpleMessageBox" TagPrefix="wsp" %> +<%@ Register Src="../UserControls/EnableAsyncTasksSupport.ascx" TagName="EnableAsyncTasksSupport" TagPrefix="wsp" %> + + + +
+
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+
+ + + + 10 + 20 + 50 + 100 + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
\ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageDriveMaps.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageDriveMaps.ascx.cs new file mode 100644 index 00000000..3f7c3a07 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageDriveMaps.ascx.cs @@ -0,0 +1,97 @@ +// Copyright (c) 2014, 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. + +using System; +using System.Web.UI.WebControls; +using WebsitePanel.EnterpriseServer; +using WebsitePanel.Providers.Common; +using WebsitePanel.Providers.HostedSolution; +using WebsitePanel.Providers.OS; +using WebsitePanel.WebPortal; + +namespace WebsitePanel.Portal.ExchangeServer +{ + public partial class EnterpriseStorageDriveMaps : WebsitePanelModuleBase + { + protected void Page_Load(object sender, EventArgs e) + { + if (!IsPostBack) + { + if (!ES.Services.EnterpriseStorage.CheckUsersDomainExists(PanelRequest.ItemID)) + { + btnAddDriveMap.Enabled = false; + + messageBox.ShowWarningMessage("WEB_SITE_IS_NOT_CREATED"); + } + } + } + + protected void btnAddDriveMap_Click(object sender, EventArgs e) + { + Response.Redirect(EditUrl("ItemID", PanelRequest.ItemID.ToString(), "create_enterprisestorage_drive_map", + "SpaceID=" + PanelSecurity.PackageId)); + } + + protected void gvDriveMaps_RowCommand(object sender, GridViewCommandEventArgs e) + { + if (e.CommandName == "DeleteItem") + { + // delete drive map + string driveLetter = e.CommandArgument.ToString(); + + try + { + ResultObject result = ES.Services.EnterpriseStorage.DeleteMappedDrive(PanelRequest.ItemID, driveLetter); + if (!result.IsSuccess) + { + messageBox.ShowMessage(result, "ENTERPRISE_STORAGE_DRIVE_MAP", "EnterpriseStorage"); + return; + } + + gvDriveMaps.DataBind(); + } + catch (Exception ex) + { + ShowErrorMessage("ENTERPRISE_STORAGE_DELETE_DRIVE_MAP", ex); + } + } + } + + protected void ddlPageSize_SelectedIndexChanged(object sender, EventArgs e) + { + gvDriveMaps.PageSize = Convert.ToInt16(ddlPageSize.SelectedValue); + + gvDriveMaps.DataBind(); + } + + protected string GetDriveImage() + { + return String.Concat("~/", DefaultPage.THEMES_FOLDER, "/", Page.Theme, "/", "Images/Exchange", "/", "net_drive16.png"); + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageDriveMaps.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageDriveMaps.ascx.designer.cs new file mode 100644 index 00000000..ccfb8647 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageDriveMaps.ascx.designer.cs @@ -0,0 +1,123 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WebsitePanel.Portal.ExchangeServer { + + + public partial class EnterpriseStorageDriveMaps { + + /// + /// asyncTasks control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.EnableAsyncTasksSupport asyncTasks; + + /// + /// imgESDM control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Image imgESDM; + + /// + /// locTitle control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locTitle; + + /// + /// messageBox control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::WebsitePanel.Portal.UserControls.SimpleMessageBox messageBox; + + /// + /// btnAddDriveMap control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnAddDriveMap; + + /// + /// SearchPanel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Panel SearchPanel; + + /// + /// locSearch control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Localize locSearch; + + /// + /// ddlPageSize control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.DropDownList ddlPageSize; + + /// + /// txtSearchValue control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox txtSearchValue; + + /// + /// cmdSearch control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.ImageButton cmdSearch; + + /// + /// gvDriveMaps control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.GridView gvDriveMaps; + + /// + /// odsEnterpriseDriveMapsPaged control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.ObjectDataSource odsEnterpriseDriveMapsPaged; + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageFolders.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageFolders.ascx index 3a0094b5..0d6d1653 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageFolders.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ExchangeServer/EnterpriseStorageFolders.ascx @@ -46,7 +46,7 @@ DataSourceID="odsEnterpriseFoldersPaged" PageSize="20"> - + @@ -55,23 +55,30 @@ - + - + - + + + + + + + + newAccounts = new List(); + //List newAccounts = new List(); accounts = accounts.Where(x => !GetPemissions().Select(p => p.Account).Contains(x.AccountName)).ToArray(); Array.Sort(accounts, CompareAccount); diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/OrganizationMenu.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/OrganizationMenu.ascx.cs index b01c53fb..ff42612c 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/OrganizationMenu.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/OrganizationMenu.ascx.cs @@ -66,7 +66,7 @@ namespace WebsitePanel.Portal //Add "Organization Home" menu item MenuItem item = new MenuItem( GetLocalizedString("Text.OrganizationHome"), - "", + "", "", PortalUtils.EditUrl("ItemID", PanelRequest.ItemID.ToString(), "organization_home", "SpaceID=" + PanelSecurity.PackageId)); @@ -363,6 +363,10 @@ namespace WebsitePanel.Portal private void PrepareEnterpriseStorageMenu(PackageContext cntx, MenuItemCollection enterpriseStorageItems) { enterpriseStorageItems.Add(CreateMenuItem("EnterpriseStorageFolders", "enterprisestorage_folders")); + + if(Utils.CheckQouta(Quotas.ENTERPRICESTORAGE_DRIVEMAPS, cntx)) + enterpriseStorageItems.Add(CreateMenuItem("EnterpriseStorageDriveMaps", "enterprisestorage_drive_maps")); + } private MenuItem CreateMenuItem(string text, string key) 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 50f6550f..84a7a6bc 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitePanel.Portal.Modules.csproj @@ -217,6 +217,20 @@ CRMStorageSettings.ascx + + EnterpriseStorageCreateDriveMap.ascx + ASPXCodeBehind + + + EnterpriseStorageCreateDriveMap.ascx + + + EnterpriseStorageDriveMaps.ascx + ASPXCodeBehind + + + EnterpriseStorageDriveMaps.ascx + EnterpriseStorageFolderGeneralSettings.ascx ASPXCodeBehind @@ -4073,6 +4087,8 @@ + + @@ -5334,6 +5350,10 @@ + + Designer + + Designer