From c16a9a6c66fc181659543ed2bc227ca5f55edb49 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Tue, 20 Jan 2015 23:12:24 -0800 Subject: [PATCH 01/15] webdav portal auth fix --- .../Security/Authentication/FormsAuthenticationService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Security/Authentication/FormsAuthenticationService.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Security/Authentication/FormsAuthenticationService.cs index 6e27366a..f802b9b8 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Security/Authentication/FormsAuthenticationService.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Security/Authentication/FormsAuthenticationService.cs @@ -33,7 +33,7 @@ namespace WebsitePanel.WebDav.Core.Security.Authentication var user = UserPrincipal.FindByIdentity(_principalContext, IdentityType.UserPrincipalName, login); - if (_principalContext.ValidateCredentials(login, password) == false && user != null) + if (user == null || _principalContext.ValidateCredentials(login, password) == false) { return null; } From d760123ef59bfba29d1261d88097caefd6004eba Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Wed, 21 Jan 2015 14:04:48 -0500 Subject: [PATCH 02/15] Added tag build-2.1.0.541 for changeset 7d0c158006ca From 3842de42600ca238e9ca5dfaa68a143870a88804 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Wed, 21 Jan 2015 23:58:27 -0800 Subject: [PATCH 03/15] fixed bugs --- WebsitePanel/Database/update_db.sql | 2 +- ...bsitePanel.Portal.Ecommerce.Modules.csproj | 93 ++++++++++++++++++- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/WebsitePanel/Database/update_db.sql b/WebsitePanel/Database/update_db.sql index c06d12de..f72a0a4b 100644 --- a/WebsitePanel/Database/update_db.sql +++ b/WebsitePanel/Database/update_db.sql @@ -7791,7 +7791,7 @@ RETURN GO IF EXISTS (SELECT * FROM SYS.OBJECTS WHERE type = 'P' AND name = 'DeleteOrganizationDeletedUser') -DROP PROCEDURE [dbo].[GetOrganizationDeletedUser] +DROP PROCEDURE [dbo].[DeleteOrganizationDeletedUser] GO CREATE PROCEDURE [dbo].[DeleteOrganizationDeletedUser] diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/Ecommerce/WebsitePanel.Portal.Ecommerce.Modules.csproj b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/Ecommerce/WebsitePanel.Portal.Ecommerce.Modules.csproj index 923cc4df..8fda74b1 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/Ecommerce/WebsitePanel.Portal.Ecommerce.Modules.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/Ecommerce/WebsitePanel.Portal.Ecommerce.Modules.csproj @@ -117,36 +117,42 @@ BillingCycles.ascx + ASPXCodeBehind BillingCycles.ascx BillingCyclesAddCycle.ascx + ASPXCodeBehind BillingCyclesAddCycle.ascx BillingCyclesEditCycle.ascx + ASPXCodeBehind BillingCyclesEditCycle.ascx Categories.ascx + ASPXCodeBehind Categories.ascx CategoriesAddCategory.ascx + ASPXCodeBehind CategoriesAddCategory.ascx CategoriesEditCategory.ascx + ASPXCodeBehind CategoriesEditCategory.ascx @@ -158,8 +164,12 @@ ASPXCodeBehind - - + + ASPXCodeBehind + + + ASPXCodeBehind + @@ -186,150 +196,175 @@ CustomerPaymentProfile.ascx + ASPXCodeBehind CustomerPaymentProfile.ascx CustomersInvoices.ascx + ASPXCodeBehind CustomersInvoices.ascx CustomersInvoicesViewInvoice.ascx + ASPXCodeBehind CustomersInvoicesViewInvoice.ascx CustomersPayments.ascx + ASPXCodeBehind CustomersPayments.ascx CustomersServices.ascx + ASPXCodeBehind CustomersServices.ascx CustomersServicesUpgradeService.ascx + ASPXCodeBehind CustomersServicesUpgradeService.ascx CustomersServicesViewService.ascx + ASPXCodeBehind CustomersServicesViewService.ascx DomainNames.ascx + ASPXCodeBehind DomainNames.ascx DomainNamesAddDomain.ascx + ASPXCodeBehind DomainNamesAddDomain.ascx DomainNamesEditDomain.ascx + ASPXCodeBehind DomainNamesEditDomain.ascx DomainRegistrarDirecti.ascx + ASPXCodeBehind DomainRegistrarDirecti.ascx DomainRegistrarEnom.ascx + ASPXCodeBehind DomainRegistrarEnom.ascx EcommerceSystemSettings.ascx + ASPXCodeBehind EcommerceSystemSettings.ascx HostingAddons.ascx + ASPXCodeBehind HostingAddons.ascx HostingAddonsAddAddon.ascx + ASPXCodeBehind HostingAddonsAddAddon.ascx HostingAddonsEditAddon.ascx + ASPXCodeBehind HostingAddonsEditAddon.ascx HostingPlans.ascx + ASPXCodeBehind HostingPlans.ascx HostingPlansAddPlan.ascx + ASPXCodeBehind HostingPlansAddPlan.ascx HostingPlansEditPlan.ascx + ASPXCodeBehind HostingPlansEditPlan.ascx NotificationNewInvoice.ascx + ASPXCodeBehind NotificationNewInvoice.ascx NotificationPaymentReceived.ascx + ASPXCodeBehind NotificationPaymentReceived.ascx NotificationServiceActivated.ascx + ASPXCodeBehind NotificationServiceActivated.ascx NotificationServiceCancelled.ascx + ASPXCodeBehind NotificationServiceCancelled.ascx NotificationServiceSuspended.ascx + ASPXCodeBehind NotificationServiceSuspended.ascx OrderFailed.ascx + ASPXCodeBehind OrderFailed.ascx @@ -343,48 +378,56 @@ PaymentMethod2Checkout.ascx + ASPXCodeBehind PaymentMethod2Checkout.ascx PaymentMethodCreditCard.ascx + ASPXCodeBehind PaymentMethodCreditCard.ascx PaymentMethodOffline.ascx + ASPXCodeBehind PaymentMethodOffline.ascx PaymentMethodPayPalAccount.ascx + ASPXCodeBehind PaymentMethodPayPalAccount.ascx 2CO_Payment.ascx + ASPXCodeBehind 2CO_Payment.ascx CreditCard_Payment.ascx + ASPXCodeBehind CreditCard_Payment.ascx Offline_Payment.ascx + ASPXCodeBehind Offline_Payment.ascx PPAccount_Payment.ascx + ASPXCodeBehind PPAccount_Payment.ascx @@ -398,30 +441,35 @@ DomainName_ServiceDetails.ascx + ASPXCodeBehind DomainName_ServiceDetails.ascx HostingAddon_ServiceDetails.ascx + ASPXCodeBehind HostingAddon_ServiceDetails.ascx HostingPlan_Brief.ascx + ASPXCodeBehind HostingPlan_Brief.ascx HostingPlan_Highlights.ascx + ASPXCodeBehind HostingPlan_Highlights.ascx HostingPlan_ServiceDetails.ascx + ASPXCodeBehind HostingPlan_ServiceDetails.ascx @@ -429,24 +477,28 @@ ProvisioningSettingsEdit.ascx + ASPXCodeBehind ProvisioningSettingsEdit.ascx QuickSignup.ascx + ASPXCodeBehind QuickSignup.ascx OrderComplete.ascx + ASPXCodeBehind OrderComplete.ascx OrderCheckout.ascx + ASPXCodeBehind OrderCheckout.ascx @@ -458,102 +510,119 @@ CatalogBreadCrumb.ascx + ASPXCodeBehind CatalogBreadCrumb.ascx StorefrontMenu.ascx + ASPXCodeBehind StorefrontMenu.ascx StorefrontOrderProduct.ascx + ASPXCodeBehind StorefrontOrderProduct.ascx StorefrontViewCategory.ascx + ASPXCodeBehind StorefrontViewCategory.ascx StorefrontWelcome.ascx + ASPXCodeBehind StorefrontWelcome.ascx StorefrontWelcomeEdit.ascx + ASPXCodeBehind StorefrontWelcomeEdit.ascx 2Checkout_Settings.ascx + ASPXCodeBehind 2Checkout_Settings.ascx AuthorizeNet_Settings.ascx + ASPXCodeBehind AuthorizeNet_Settings.ascx OfflinePayment_Settings.ascx + ASPXCodeBehind OfflinePayment_Settings.ascx PayPalPro_Settings.ascx + ASPXCodeBehind PayPalPro_Settings.ascx PayPalStandard_Settings.ascx + ASPXCodeBehind PayPalStandard_Settings.ascx Taxations.ascx + ASPXCodeBehind Taxations.ascx TaxationsAddTax.ascx + ASPXCodeBehind TaxationsAddTax.ascx TaxationsEditTax.ascx + ASPXCodeBehind TaxationsEditTax.ascx TermsAndConditions.ascx + ASPXCodeBehind TermsAndConditions.ascx TermsAndConditionsEdit.ascx + ASPXCodeBehind TermsAndConditionsEdit.ascx AddonProducts.ascx + ASPXCodeBehind AddonProducts.ascx @@ -570,120 +639,140 @@ ChoosePaymentMethod.ascx + ASPXCodeBehind ChoosePaymentMethod.ascx CreateUserAccount.ascx + ASPXCodeBehind CreateUserAccount.ascx CustomerInvoiceTemplated.ascx + ASPXCodeBehind CustomerInvoiceTemplated.ascx DomainNameBillingCycles.ascx + ASPXCodeBehind DomainNameBillingCycles.ascx EmailNotificationEditor.ascx + ASPXCodeBehind EmailNotificationEditor.ascx HostingAddonOneTimeFee.ascx + ASPXCodeBehind HostingAddonOneTimeFee.ascx HostingPlanBillingCycles.ascx + ASPXCodeBehind HostingPlanBillingCycles.ascx HostingPlanQuotas.ascx + ASPXCodeBehind HostingPlanQuotas.ascx LoginUserAccount.ascx + ASPXCodeBehind LoginUserAccount.ascx ManualPaymentAdd.ascx + ASPXCodeBehind ManualPaymentAdd.ascx PlanDomainOption.ascx + ASPXCodeBehind PlanDomainOption.ascx PlanHostingAddons.ascx + ASPXCodeBehind PlanHostingAddons.ascx ProductHighlights.ascx + ASPXCodeBehind ProductHighlights.ascx QuickHostingAddon.ascx + ASPXCodeBehind QuickHostingAddon.ascx QuickHostingPlanCycles.ascx + ASPXCodeBehind QuickHostingPlanCycles.ascx QuickHostingPlans.ascx + ASPXCodeBehind QuickHostingPlans.ascx PathBreadCrumb.ascx + ASPXCodeBehind PathBreadCrumb.ascx ProductCategories.ascx + ASPXCodeBehind ProductCategories.ascx UserAccountDetails.ascx + ASPXCodeBehind UserAccountDetails.ascx ViewProductDetails.ascx + ASPXCodeBehind ViewProductDetails.ascx From 87dd3877930128a516a8995fdf601504b8bb81cd Mon Sep 17 00:00:00 2001 From: Virtuworks Date: Thu, 22 Jan 2015 18:55:55 -0500 Subject: [PATCH 04/15] Added tag build-2.1.0.542 for changeset 769c090649e2 From 8f22fea5f40707a2df6d22e532da19f597f98916 Mon Sep 17 00:00:00 2001 From: Alexander Trofimov Date: Fri, 23 Jan 2015 13:31:53 +0700 Subject: [PATCH 05/15] Fix redirect when add\change IP address in the edit server page and in IP list page with paging --- .../WebsitePanel/Code/Framework/Utils.cs | 4 ++-- .../WebsitePanel/IPAddresses.ascx | 2 +- .../WebsitePanel/IPAddresses.ascx.cs | 18 +++++++++++++++++- .../ServerIPAddressesControl.ascx.cs | 17 ++++++++++++++++- .../WebsitePanel/ServersEditServer.ascx.cs | 4 ++-- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Framework/Utils.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Framework/Utils.cs index 2285cd13..428ab43f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Framework/Utils.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Code/Framework/Utils.cs @@ -46,7 +46,7 @@ namespace WebsitePanel.Portal /// /// Summary description for Utils. /// Name of the parameter to add. /// Value for the parameter to add. /// Url with added parameter. - public static Uri AddParameterToUrl(Uri url, string paramName, string paramValue) + public static Uri AddParameter(this Uri url, string paramName, string paramValue) { var uriBuilder = new UriBuilder(url); var query = HttpUtility.ParseQueryString(uriBuilder.Query); diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddresses.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddresses.ascx index 11119fd1..62389f09 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddresses.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddresses.ascx @@ -51,7 +51,7 @@ - + <%# Eval("ExternalIP") %> diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddresses.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddresses.ascx.cs index b3ed2b40..950cd86d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddresses.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/IPAddresses.ascx.cs @@ -45,6 +45,8 @@ namespace WebsitePanel.Portal gvIPAddresses.PageSize = UsersHelper.GetDisplayItemsPerPage(); ddlItemsPerPage.SelectedValue = gvIPAddresses.PageSize.ToString(); + gvIPAddresses.PageIndex = PageIndex; + // pool if (!String.IsNullOrEmpty(PanelRequest.PoolId)) ddlPools.SelectedValue = PanelRequest.PoolId; @@ -69,6 +71,7 @@ namespace WebsitePanel.Portal bool vps = ddlPools.SelectedIndex > 1; gvIPAddresses.Columns[3].Visible = vps; } + protected void odsIPAddresses_Selected(object sender, ObjectDataSourceStatusEventArgs e) { if (e.Exception != null) @@ -84,10 +87,23 @@ namespace WebsitePanel.Portal return PortalUtils.GetSpaceHomePageUrl(spaceId); } + public string GetReturnUrl() + { + var returnUrl = Request.Url.AddParameter("Page", gvIPAddresses.PageIndex.ToString()); + return Uri.EscapeDataString("~" + returnUrl.PathAndQuery); + } + + public int PageIndex + { + get + { + return PanelRequest.GetInt("Page", 0); + } + } protected void btnAddItem_Click(object sender, EventArgs e) { - Response.Redirect(EditUrl("PoolID", ddlPools.SelectedValue, "add_ip"), true); + Response.Redirect(EditUrl("PoolID", ddlPools.SelectedValue, "add_ip", "ReturnUrl=" + GetReturnUrl()), true); } protected void ddlItemsPerPage_SelectedIndexChanged(object sender, EventArgs e) diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ServerIPAddressesControl.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ServerIPAddressesControl.ascx.cs index 6718425e..fc805eee 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ServerIPAddressesControl.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ServerIPAddressesControl.ascx.cs @@ -43,6 +43,18 @@ namespace WebsitePanel.Portal { protected void Page_Load(object sender, EventArgs e) { + if (!IsPostBack) + { + gvIPAddresses.PageIndex = PageIndex; + } + } + + public int PageIndex + { + get + { + return PanelRequest.GetInt("IpAddressesPage", 0); + } } public string EditModuleUrl(string key, string keyVal, string ctrlKey) @@ -57,7 +69,10 @@ namespace WebsitePanel.Portal public string GetReturnUrl() { - var returnUrl = Utils.AddParameterToUrl(Request.Url, "IpAddressesCollapsed", "False"); + var returnUrl = Request.Url + .AddParameter("IpAddressesCollapsed", "False") + .AddParameter("IpAddressesPage", gvIPAddresses.PageIndex.ToString()); + return Uri.EscapeDataString("~" + returnUrl.PathAndQuery); } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ServersEditServer.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ServersEditServer.ascx.cs index c31abfbd..3bee6d7d 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ServersEditServer.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/ServersEditServer.ascx.cs @@ -58,9 +58,9 @@ namespace WebsitePanel.Portal ShowErrorMessage("SERVER_GET_SERVER", ex); return; } - } - IPAddressesHeader.IsCollapsed = IsIpAddressesCollapsed; + IPAddressesHeader.IsCollapsed = IsIpAddressesCollapsed; + } } private void BindTools() From 29747087ff909a1249c39e6850793888d5b3a8e5 Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Fri, 23 Jan 2015 00:46:08 -0800 Subject: [PATCH 06/15] webdav portal multiselect + delete ability added --- .../Config/Entities/SessionKeysCollection.cs | 22 ++++ .../WebConfigSections/SessionKeysElement.cs | 4 +- .../Exceptions/WebDavException.cs | 14 ++ .../WebsitePanel.WebDav.Core/IFolder.cs | 2 +- .../WebsitePanel.WebDav.Core/IResource.cs | 10 ++ .../Interfaces/Managers/IWebDavManager.cs | 1 + .../Managers/WebDavManager.cs | 46 +++++-- .../Resources/WebDavResources.Designer.cs | 72 ++++++++++ .../Resources/WebDavResources.resx | 123 ++++++++++++++++++ .../WebDavAuthorizationService.cs | 57 ++++++-- .../WebsitePanel.WebDav.Core.csproj | 9 ++ .../App_Start/BundleConfig.cs | 6 +- .../App_Start/RouteConfig.cs | 6 + .../Content/Site.css | 33 +++++ .../Controllers/AccountController.cs | 2 + .../Controllers/FileSystemController.cs | 52 +++++++- .../FormValueRequiredAttribute.cs | 21 +++ .../Models/AccountModel.cs | 3 +- .../Models/Common/BaseModel.cs | 15 +++ .../Models/Common/Enums/MessageType.cs | 10 ++ .../Models/Common/Message.cs | 10 ++ .../Models/ErrorModel.cs | 3 +- .../Models/FileSystem/DeleteFilesModel.cs | 15 +++ .../Models/ModelForWebDav.cs | 3 +- .../Models/OfficeOnlineModel.cs | 6 +- .../Scripts/appScripts/dialogs.js | 93 ++++++++++--- .../Scripts/appScripts/fileBrowsing.js | 89 +++++++++++++ .../Scripts/appScripts/messages.js | 55 ++++++++ .../Scripts/appScripts/wsp.js | 46 +++++++ .../UI/Resources.Designer.cs | 72 ++++++++++ .../UI/Resources.resx | 24 ++++ .../UI/Routes/FileSystemRouteNames.cs | 2 + .../Views/FileSystem/ShowContent.cshtml | 36 +++-- .../Views/FileSystem/_ResoursePartial.cshtml | 15 ++- .../Views/Shared/_ConfirmDialog.cshtml | 20 +++ .../Views/Shared/_Layout.cshtml | 22 +++- .../WebsitePanel.WebDavPortal/Web.config | 2 + .../WebsitePanel.WebDavPortal.csproj | 9 ++ 38 files changed, 964 insertions(+), 66 deletions(-) create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDav.Core/Resources/WebDavResources.Designer.cs create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDav.Core/Resources/WebDavResources.resx create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/CustomAttributes/FormValueRequiredAttribute.cs create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/BaseModel.cs create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/Enums/MessageType.cs create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/Message.cs create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/FileSystem/DeleteFilesModel.cs create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/fileBrowsing.js create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/messages.js create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/wsp.js create mode 100644 WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/_ConfirmDialog.cshtml diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/Entities/SessionKeysCollection.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/Entities/SessionKeysCollection.cs index 057be2cf..f9337401 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/Entities/SessionKeysCollection.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/Entities/SessionKeysCollection.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; using System.Linq; +using WebsitePanel.EnterpriseServer.Base.HostedSolution; +using WebsitePanel.WebDav.Core.Config.WebConfigSections; using WebsitePanel.WebDavPortal.WebConfigSections; namespace WebsitePanel.WebDav.Core.Config.Entities @@ -33,6 +35,26 @@ namespace WebsitePanel.WebDav.Core.Config.Entities } } + public string UserGroupsKey + { + get + { + SessionKeysElement sessionKey = + _sessionKeys.FirstOrDefault(x => x.Key == SessionKeysElement.UserGroupsKey); + return sessionKey != null ? sessionKey.Value : null; + } + } + + public string WebDavRootFoldersPermissions + { + get + { + SessionKeysElement sessionKey = + _sessionKeys.FirstOrDefault(x => x.Key == SessionKeysElement.WebDavRootFolderPermissionsKey); + return sessionKey != null ? sessionKey.Value : null; + } + } + public string ResourseRenderCount { get diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/WebConfigSections/SessionKeysElement.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/WebConfigSections/SessionKeysElement.cs index cfe2e0b9..ca2a44fd 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/WebConfigSections/SessionKeysElement.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Config/WebConfigSections/SessionKeysElement.cs @@ -1,6 +1,6 @@ using System.Configuration; -namespace WebsitePanel.WebDavPortal.WebConfigSections +namespace WebsitePanel.WebDav.Core.Config.WebConfigSections { public class SessionKeysElement : ConfigurationElement { @@ -10,6 +10,8 @@ namespace WebsitePanel.WebDavPortal.WebConfigSections public const string AccountInfoKey = "AccountInfoSessionKey"; public const string AuthTicketKey = "AuthTicketKey"; public const string WebDavManagerKey = "WebDavManagerSessionKey"; + public const string UserGroupsKey = "UserGroupsKey"; + public const string WebDavRootFolderPermissionsKey = "WebDavRootFolderPermissionsKey"; public const string ResourseRenderCountKey = "ResourseRenderCountSessionKey"; public const string ItemIdSessionKey = "ItemId"; diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Exceptions/WebDavException.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Exceptions/WebDavException.cs index ea5a647b..3e4895a5 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Exceptions/WebDavException.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Exceptions/WebDavException.cs @@ -4,5 +4,19 @@ namespace WebsitePanel.WebDav.Core.Exceptions { public class WebDavException : Exception { + public WebDavException() + : base() { } + + public WebDavException(string message) + : base(message) { } + + public WebDavException(string format, params object[] args) + : base(string.Format(format, args)) { } + + public WebDavException(string message, Exception innerException) + : base(message, innerException) { } + + public WebDavException(string format, Exception innerException, params object[] args) + : base(string.Format(format, args), innerException) { } } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/IFolder.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/IFolder.cs index eb1e1f99..1f45f389 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/IFolder.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/IFolder.cs @@ -148,7 +148,7 @@ namespace WebsitePanel.WebDav.Core public IResource GetResource(string name) { IHierarchyItem item = - _children.Single(i => i.ItemType == ItemType.Resource && i.DisplayName.Trim('/') == name.Trim('/')); + _children.Single(i => i.DisplayName.Trim('/') == name.Trim('/')); var resource = new WebDavResource(); resource.SetCredentials(_credentials); resource.SetHierarchyItem(item); diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/IResource.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/IResource.cs index 6766553b..4470ac67 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/IResource.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/IResource.cs @@ -428,6 +428,15 @@ namespace WebsitePanel.WebDav.Core _lastModified = lastModified; } + /// + /// For internal use only. + /// + /// + public void SetItemType(ItemType type) + { + _itemType = type; + } + /// /// For internal use only. /// @@ -541,6 +550,7 @@ namespace WebsitePanel.WebDav.Core SetHref(item.Href); SetLastModified(item.LastModified); SetProperties(item.Properties); + SetItemType(item.ItemType); } } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Interfaces/Managers/IWebDavManager.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Interfaces/Managers/IWebDavManager.cs index 2c62309f..f6611a66 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Interfaces/Managers/IWebDavManager.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Interfaces/Managers/IWebDavManager.cs @@ -12,5 +12,6 @@ namespace WebsitePanel.WebDav.Core.Interfaces.Managers void UploadFile(string path, HttpPostedFileBase file); IResource GetResource(string path); string GetFileUrl(string path); + void DeleteResource(string path); } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Managers/WebDavManager.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Managers/WebDavManager.cs index fc6ab6ff..9575f2d2 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Managers/WebDavManager.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Managers/WebDavManager.cs @@ -13,6 +13,7 @@ using WebsitePanel.WebDav.Core.Config; using WebsitePanel.WebDav.Core.Exceptions; using WebsitePanel.WebDav.Core.Extensions; using WebsitePanel.WebDav.Core.Interfaces.Managers; +using WebsitePanel.WebDav.Core.Resources; using WebsitePanel.WebDav.Core.Security.Cryptography; using WebsitePanel.WebDav.Core.Wsp.Framework; @@ -70,7 +71,7 @@ namespace WebsitePanel.WebDav.Core.Managers _cryptography.Decrypt(WspContext.User.EncryptedPassword), WebDavAppConfigManager.Instance.UserDomain); - _currentFolder = _webDavSession.OpenFolder(string.Format("{0}{1}/{2}", WebDavAppConfigManager.Instance.WebdavRoot, WspContext.User.OrganizationId, pathPart)); + _currentFolder = _webDavSession.OpenFolder(string.Format("{0}{1}/{2}", WebDavAppConfigManager.Instance.WebdavRoot, WspContext.User.OrganizationId, pathPart.TrimStart('/'))); } children = _currentFolder.GetChildren().Where(x => !WebDavAppConfigManager.Instance.ElementsRendering.ElementsToIgnore.Contains(x.DisplayName.Trim('/'))).ToArray(); @@ -95,15 +96,9 @@ namespace WebsitePanel.WebDav.Core.Managers OpenFolder(folder); - try - { - IResource resource = _currentFolder.GetResource(resourceName); + IResource resource = _currentFolder.GetResource(resourceName); - return true; - } - catch (Exception e){} - - return false; + return resource.ItemType != ItemType.Folder; } @@ -148,6 +143,27 @@ namespace WebsitePanel.WebDav.Core.Managers resource.Upload(bytes); } + public void DeleteResource(string path) + { + path = RemoveLeadingFromPath(path, "office365"); + path = RemoveLeadingFromPath(path, WspContext.User.OrganizationId); + + string folderPath = GetFileFolder(path); + + OpenFolder(folderPath); + + var resourceName = GetResourceName(path); + + IResource resource = _currentFolder.GetResource(resourceName); + + if (resource.ItemType == ItemType.Folder && GetFoldersItemsCount(path) > 0) + { + throw new WebDavException(string.Format(WebDavResources.FolderIsNotEmptyFormat, resource.DisplayName)); + } + + resource.Delete(); + } + public IResource GetResource(string path) { try @@ -210,8 +226,20 @@ namespace WebsitePanel.WebDav.Core.Managers return rootFolders; } + private int GetFoldersItemsCount(string path) + { + var items = OpenFolder(path); + + return items.Count(); + } + #region Helpers + private string RemoveLeadingFromPath(string pathPart, string toRemove) + { + return pathPart.StartsWith('/' + toRemove) ? pathPart.Substring(toRemove.Length + 1) : pathPart; + } + private byte[] ReadFully(Stream input) { var buffer = new byte[16 * 1024]; diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Resources/WebDavResources.Designer.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Resources/WebDavResources.Designer.cs new file mode 100644 index 00000000..2cb3ad80 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Resources/WebDavResources.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.33440 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WebsitePanel.WebDav.Core.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class WebDavResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal WebDavResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WebsitePanel.WebDav.Core.Resources.WebDavResources", typeof(WebDavResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Folder {0} is not empty.. + /// + internal static string FolderIsNotEmptyFormat { + get { + return ResourceManager.GetString("FolderIsNotEmptyFormat", resourceCulture); + } + } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Resources/WebDavResources.resx b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Resources/WebDavResources.resx new file mode 100644 index 00000000..fb231645 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Resources/WebDavResources.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Folder {0} is not empty. + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Security/Authorization/WebDavAuthorizationService.cs b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Security/Authorization/WebDavAuthorizationService.cs index 2bc4d767..e632b873 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Security/Authorization/WebDavAuthorizationService.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/Security/Authorization/WebDavAuthorizationService.cs @@ -1,5 +1,10 @@ using System; +using System.Collections.Generic; using System.Linq; +using System.Web; +using WebsitePanel.EnterpriseServer.Base.HostedSolution; +using WebsitePanel.Providers.HostedSolution; +using WebsitePanel.WebDav.Core.Config; using WebsitePanel.WebDav.Core.Interfaces.Security; using WebsitePanel.WebDav.Core.Security.Authentication.Principals; using WebsitePanel.WebDav.Core.Security.Authorization.Enums; @@ -27,18 +32,9 @@ namespace WebsitePanel.WebDav.Core.Security.Authorization var rootFolder = GetRootFolder(path); - var userGroups = WSP.Services.Organizations.GetSecurityGroupsByMember(principal.ItemId, principal.AccountId); + var userGroups = GetUserSecurityGroups(principal); - var rootFolders = WSP.Services.EnterpriseStorage.GetEnterpriseFolders(principal.ItemId); - - var esRootFolder = rootFolders.FirstOrDefault(x => x.Name == rootFolder); - - if (esRootFolder == null) - { - return WebDavPermissions.None; - } - - var permissions = WSP.Services.EnterpriseStorage.GetEnterpriseFolderPermissions(principal.ItemId, esRootFolder.Name); + var permissions = GetFolderEsPermissions(principal, rootFolder); foreach (var permission in permissions) { @@ -65,5 +61,44 @@ namespace WebsitePanel.WebDav.Core.Security.Authorization { return path.Split(new[]{'/'}, StringSplitOptions.RemoveEmptyEntries)[0]; } + + private IEnumerable GetFolderEsPermissions(WspPrincipal principal, string rootFolderName) + { + var dictionary = HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.WebDavRootFoldersPermissions] as + Dictionary>; + + if (dictionary == null) + { + dictionary = new Dictionary>(); + + var rootFolders = WSP.Services.EnterpriseStorage.GetEnterpriseFolders(principal.ItemId); + + foreach (var rootFolder in rootFolders) + { + var permissions = WSP.Services.EnterpriseStorage.GetEnterpriseFolderPermissions(principal.ItemId, rootFolder.Name); + + dictionary.Add(rootFolder.Name, permissions); + } + + HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.WebDavRootFoldersPermissions] = dictionary; + } + + return dictionary.ContainsKey(rootFolderName) ? dictionary[rootFolderName] : new ESPermission[0]; + } + + private IEnumerable GetUserSecurityGroups(WspPrincipal principal) + { + var groups = HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.UserGroupsKey] as + IEnumerable; + + if (groups == null) + { + groups = WSP.Services.Organizations.GetSecurityGroupsByMember(principal.ItemId, principal.AccountId); + + HttpContext.Current.Session[WebDavAppConfigManager.Instance.SessionKeys.UserGroupsKey] = groups; + } + + return groups ?? new ExchangeAccount[0]; + } } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/WebsitePanel.WebDav.Core.csproj b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/WebsitePanel.WebDav.Core.csproj index ff78a246..5f810c52 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDav.Core/WebsitePanel.WebDav.Core.csproj +++ b/WebsitePanel/Sources/WebsitePanel.WebDav.Core/WebsitePanel.WebDav.Core.csproj @@ -147,6 +147,11 @@ True HttpErrors.resx + + True + True + WebDavResources.resx + @@ -175,6 +180,10 @@ ResXFileCodeGenerator HttpErrors.Designer.cs + + ResXFileCodeGenerator + WebDavResources.Designer.cs + diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/BundleConfig.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/BundleConfig.cs index b9eef087..411062bb 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/BundleConfig.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/BundleConfig.cs @@ -27,7 +27,11 @@ namespace WebsitePanel.WebDavPortal "~/Scripts/appScripts/recalculateResourseHeight.js", "~/Scripts/appScripts/uploadingData2.js", "~/Scripts/appScripts/authentication.js", - "~/Scripts/appScripts/dialogs.js")); + "~/Scripts/appScripts/messages.js", + "~/Scripts/appScripts/fileBrowsing.js", + "~/Scripts/appScripts/dialogs.js", + "~/Scripts/appScripts/wsp.js" + )); bundles.Add(new ScriptBundle("~/bundles/authScripts").Include( "~/Scripts/appScripts/authentication.js")); diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/RouteConfig.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/RouteConfig.cs index 0abc4a09..c757a379 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/RouteConfig.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/App_Start/RouteConfig.cs @@ -42,6 +42,12 @@ namespace WebsitePanel.WebDavPortal #endregion + routes.MapRoute( + name: FileSystemRouteNames.DeleteFiles, + url: "files-group-action/delete", + defaults: new { controller = "FileSystem", action = "DeleteFiles" } + ); + routes.MapRoute( name: FileSystemRouteNames.UploadFile, url: "upload-file/{org}/{*pathPart}", diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Content/Site.css b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Content/Site.css index 88729f71..93f07e0f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Content/Site.css +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Content/Site.css @@ -26,6 +26,25 @@ textarea { .element-container { margin-bottom: 15px; text-align:center; + cursor: pointer; +} + +.selected-file { + box-sizing:border-box; + -moz-box-sizing:border-box; + -webkit-box-sizing:border-box; + border: 1px solid rgb(80, 152, 249); +} + +.selected-file div.selected-element-overlay { + position:absolute; + top:0px; + left: 0px; + width:100%; + height:100%; + background:rgb(200, 224, 255); + opacity:0.3; + pointer-events: none; } #errorMessage { @@ -54,4 +73,18 @@ textarea { .modal-vertical-centered { margin-top: 25%; +} + + +.file-actions-menu { + margin-top: 10px; + margin-bottom: 15px; +} + +.file-actions-menu .file-deletion { + display: none; +} + +#message-area { + margin-top: 15px; } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs index 268a0b96..2642f2f5 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/AccountController.cs @@ -6,6 +6,8 @@ using WebsitePanel.WebDav.Core.Config; using WebsitePanel.WebDav.Core.Security.Authentication; using WebsitePanel.WebDav.Core.Security.Cryptography; using WebsitePanel.WebDavPortal.Models; +using WebsitePanel.WebDavPortal.Models.Common; +using WebsitePanel.WebDavPortal.Models.Common.Enums; using WebsitePanel.WebDavPortal.UI.Routes; using WebsitePanel.WebDav.Core.Interfaces.Security; using WebsitePanel.WebDav.Core; diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/FileSystemController.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/FileSystemController.cs index 2ac65019..1d7f9187 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/FileSystemController.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Controllers/FileSystemController.cs @@ -19,6 +19,10 @@ using WebsitePanel.WebDavPortal.CustomAttributes; using WebsitePanel.WebDavPortal.Extensions; using WebsitePanel.WebDavPortal.Models; using System.Net; +using WebsitePanel.WebDavPortal.Models.Common; +using WebsitePanel.WebDavPortal.Models.Common.Enums; +using WebsitePanel.WebDavPortal.Models.FileSystem; +using WebsitePanel.WebDavPortal.UI; using WebsitePanel.WebDavPortal.UI.Routes; namespace WebsitePanel.WebDavPortal.Controllers @@ -72,7 +76,7 @@ namespace WebsitePanel.WebDavPortal.Controllers return View(model); } - catch (UnauthorizedException) + catch (UnauthorizedException e) { throw new HttpException(404, "Not Found"); } @@ -121,5 +125,51 @@ namespace WebsitePanel.WebDavPortal.Controllers return RedirectToRoute(FileSystemRouteNames.ShowContentPath); } + + [HttpPost] + public JsonResult DeleteFiles(IEnumerable filePathes = null) + { + var model = new DeleteFilesModel(); + + if (filePathes == null) + { + model.Messages.Add(new Message + { + Type = MessageType.Error, + Value = Resources.NoFilesAreSelected + }); + + return Json(model); + } + + foreach (var file in filePathes) + { + try + { + _webdavManager.DeleteResource(Server.UrlDecode(file)); + + model.DeletedFiles.Add(file); + } + catch (WebDavException exception) + { + model.Messages.Add(new Message + { + Type = MessageType.Error, + Value = exception.Message + }); + } + } + + if (model.DeletedFiles.Any()) + { + model.Messages.Insert(0, new Message + { + Type = MessageType.Success, + Value = string.Format(Resources.ItemsWasRemovedFormat, model.DeletedFiles.Count) + }); + } + + return Json(model); + } } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/CustomAttributes/FormValueRequiredAttribute.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/CustomAttributes/FormValueRequiredAttribute.cs new file mode 100644 index 00000000..be9fd6e1 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/CustomAttributes/FormValueRequiredAttribute.cs @@ -0,0 +1,21 @@ +using System.Reflection; +using System.Web.Mvc; + +namespace WebsitePanel.WebDavPortal.CustomAttributes +{ + public class FormValueRequiredAttribute : ActionMethodSelectorAttribute + { + private readonly string _submitButtonName; + + public FormValueRequiredAttribute(string submitButtonName) + { + _submitButtonName = submitButtonName; + } + + public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) + { + var value = controllerContext.HttpContext.Request.Form[_submitButtonName]; + return !string.IsNullOrEmpty(value); + } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/AccountModel.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/AccountModel.cs index e11f8956..ecf7ed80 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/AccountModel.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/AccountModel.cs @@ -1,10 +1,11 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using WebsitePanel.Providers.HostedSolution; +using WebsitePanel.WebDavPortal.Models.Common; namespace WebsitePanel.WebDavPortal.Models { - public class AccountModel + public class AccountModel : BaseModel { [Required] [Display(Name = @"Login")] diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/BaseModel.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/BaseModel.cs new file mode 100644 index 00000000..24c96da1 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/BaseModel.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Web.Mvc; + +namespace WebsitePanel.WebDavPortal.Models.Common +{ + public class BaseModel + { + public BaseModel() + { + Messages = new List(); + } + + public List Messages { get; private set; } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/Enums/MessageType.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/Enums/MessageType.cs new file mode 100644 index 00000000..bc0a2eda --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/Enums/MessageType.cs @@ -0,0 +1,10 @@ +namespace WebsitePanel.WebDavPortal.Models.Common.Enums +{ + public enum MessageType + { + Success, + Info, + Warning, + Error + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/Message.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/Message.cs new file mode 100644 index 00000000..54bdc68d --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/Common/Message.cs @@ -0,0 +1,10 @@ +using WebsitePanel.WebDavPortal.Models.Common.Enums; + +namespace WebsitePanel.WebDavPortal.Models.Common +{ + public class Message + { + public MessageType Type {get;set;} + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/ErrorModel.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/ErrorModel.cs index 84ca7b1c..bd62b88e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/ErrorModel.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/ErrorModel.cs @@ -1,8 +1,9 @@ using System; +using WebsitePanel.WebDavPortal.Models.Common; namespace WebsitePanel.WebDavPortal.Models { - public class ErrorModel + public class ErrorModel : BaseModel { public int HttpStatusCode { get; set; } public string Message { get; set; } diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/FileSystem/DeleteFilesModel.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/FileSystem/DeleteFilesModel.cs new file mode 100644 index 00000000..892f88cb --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/FileSystem/DeleteFilesModel.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using WebsitePanel.WebDavPortal.Models.Common; + +namespace WebsitePanel.WebDavPortal.Models.FileSystem +{ + public class DeleteFilesModel : BaseModel + { + public DeleteFilesModel() + { + DeletedFiles = new List(); + } + + public List DeletedFiles { get; set; } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/ModelForWebDav.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/ModelForWebDav.cs index b5d74661..bb6f722b 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/ModelForWebDav.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/ModelForWebDav.cs @@ -1,10 +1,11 @@ using System.Collections.Generic; using WebsitePanel.WebDav.Core.Client; using WebsitePanel.WebDav.Core.Security.Authorization.Enums; +using WebsitePanel.WebDavPortal.Models.Common; namespace WebsitePanel.WebDavPortal.Models { - public class ModelForWebDav + public class ModelForWebDav : BaseModel { public IEnumerable Items { get; set; } public string UrlSuffix { get; set; } diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/OfficeOnlineModel.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/OfficeOnlineModel.cs index 2805d17b..1fe27ec1 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/OfficeOnlineModel.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Models/OfficeOnlineModel.cs @@ -1,6 +1,8 @@ -namespace WebsitePanel.WebDavPortal.Models +using WebsitePanel.WebDavPortal.Models.Common; + +namespace WebsitePanel.WebDavPortal.Models { - public class OfficeOnlineModel + public class OfficeOnlineModel : BaseModel { public string Url { get; set; } public string FileName { get; set; } diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/dialogs.js b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/dialogs.js index c385e81a..488dd411 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/dialogs.js +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/dialogs.js @@ -1,20 +1,79 @@ -var processDialog; -processDialog = processDialog || (function () { - var processDialogDiv = $('#processDialog'); +function WspDialogs() { + this.settings = { dialogId: "#confirm-dialog", processDialogId: "#processDialog" }; +} + +WspDialogs.prototype = +{ + showConfirmDialog: function(title, content, positiveButton, positiveClickFunction, dialogId) { + dialogId = dialogId || this.settings.dialogId; + + //title replace + if (title) { + $(dialogId).find('.modal-title').empty(); + $(dialogId).find('.modal-title').text(title); + } + + //body replace + $(dialogId).find('.modal-body').empty(); + $(dialogId).find('.modal-body').html(content); + + //title replace + if (positiveButton) { + $(dialogId).find('.modal-footer .positive-button').empty(); + $(dialogId).find('.modal-footer .positive-button').text(positiveButton); + } + + //binding click event + $(dialogId).find('.modal-footer .positive-button').unbind('click'); + $(dialogId).find('.modal-footer .positive-button').click(positiveClickFunction); + + $(dialogId).modal(); + }, + + showProcessDialog: function() { + $(this.settings.processDialogId).modal(); + }, + + hideProcessDialog: function() { + $(this.settings.processDialogId).modal('hide'); +} +}; + +/* +wsp.dialogs = wsp.dialogs || (function () { + var settings = { dialogId: "#confirm-dialog" }; + return { - showPleaseWait: function () { + settings: settings, + + showConfirmDialog : function (title, content, positiveButton, positiveClickFunction, dialogId) { + dialogId = dialogId || this.settings.dialogId; + + //title replace + if (title) { + $(dialogId).find('.modal-title').empty(); + $(dialogId).find('.modal-title').text(title); + } + + //body replace + $(dialogId).find('.modal-body').empty(); + $(dialogId).find('.modal-body').html(content); + + //title replace + if (positiveButton) { + $(dialogId).find('.modal-footer .positive-button').empty(); + $(dialogId).find('.modal-footer .positive-button').text(positiveButton); + } + + //binding click event + $(dialogId).find('.modal-footer .positive-button').unbind('click'); + $(dialogId).find('.modal-footer .positive-button').click(positiveClickFunction); + + $(dialogId).modal(); + }, + + showProcessDialog: function () { $('#processDialog').modal(); - }, - hidePleaseWait: function () { - $('#processDialog').modal('hide'); - }, - + } }; -})(); - - -$(document).ready(function() { - $('.processing-dialog').click(function () { - processDialog.showPleaseWait(); - }); -}); \ No newline at end of file +})();*/ \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/fileBrowsing.js b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/fileBrowsing.js new file mode 100644 index 00000000..0c688721 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/fileBrowsing.js @@ -0,0 +1,89 @@ +function WspFileBrowser() { + this.settings = { deletionBlockSelector: ".file-actions-menu .file-deletion", deletionUrl: "files-group-action/delete1" }; +} + +WspFileBrowser.prototype = { + setSettings: function(options) { + this.settings = $.extend(this.settings, options); + }, + + clearAllSelectedItems: function() { + $('.element-container').removeClass("selected-file"); + }, + + selectItem: function(item) { + $(item).addClass("selected-file"); + }, + + openItem: function(item) { + var links = $(item).find('.file-link'); + + if (links.length != 0) { + links[0].click(); + } + }, + + getSelectedItemsCount: function() { + return $('.element-container.selected-file').length; + }, + + getSelectedItemsPaths: function() { + return $('.element-container.selected-file a').map(function() { + return $(this).attr('href'); + }).get(); + }, + + deleteSelectedItems: function(e) { + $.ajax({ + type: 'POST', + url: wsp.fileBrowser.settings.deletionUrl, + data: { filePathes: wsp.fileBrowser.getSelectedItemsPaths() }, + dataType: "json", + success: function(model) { + wsp.messages.showMessages(model.Messages); + + wsp.fileBrowser.clearDeletedItems(model.DeletedFiles); + + wsp.fileBrowser.refreshDeletionBlock(); + + wsp.dialogs.hideProcessDialog(); + }, + error: function(jqXHR, textStatus, errorThrown) { + wsp.messages.addErrorMessage(errorThrown); + wsp.fileBrowser.refreshDeletionBlock(); + wsp.dialogs.hideProcessDialog(); + } + }); + + wsp.dialogs.showProcessDialog(); + }, + + clearDeletedItems: function(items) { + $.each(items, function(i, item) { + $('.element-container').has('a[href="' + item + '"]').remove(); + }); + }, + refreshDeletionBlock: function() { + if (this.getSelectedItemsCount() > 0) { + + $(this.settings.deletionBlockSelector).css('display', 'inline-block'); + + } else { + $(this.settings.deletionBlockSelector).hide(); + } + } +}; + + + + + + + + + + + + + + diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/messages.js b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/messages.js new file mode 100644 index 00000000..d2d4e691 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/messages.js @@ -0,0 +1,55 @@ +function WspMessager(messageDivId) { + this.settings = { + messageDivId: messageDivId, + successClass: "alert-success", + infoClass: "alert-info", + warningClass: "alert-warning", + dangerClass: "alert-danger", + messageDivtemplate: '' + }; +} + +WspMessager.prototype = { + addMessage: function(cssClass, message) { + var messageDiv = jQuery.validator.format(this.settings.messageDivtemplate, cssClass, message); + + $(messageDiv).appendTo(this.settings.messageDivId); + }, + + addSuccessMessage: function(message) { + this.addMessage(this.settings.successClass, message); + }, + + addInfoMessage: function(message) { + this.addMessage(this.settings.infoClass, message); + }, + + addWarningMessage : function (message) { + this.addMessage(this.settings.warningClass, message); + }, + + addErrorMessage: function (message) { + this.addMessage(this.settings.dangerClass, message); + }, + + showMessages: function (messages) { + var objthis = this; + + $.each(messages, function(i, message) { + + if ((message.Type == 0)) { + objthis.addSuccessMessage(message.Value); + } + else if (message.Type == 1) { + objthis.addInfoMessage(message.Value); + } + else if (message.Type == 2) { + objthis.addWarningMessage(message.Value); + } + else if (message.Type == 3) { + objthis.addErrorMessage(message.Value); + } + } + ); + } +}; diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/wsp.js b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/wsp.js new file mode 100644 index 00000000..897b6f7a --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Scripts/appScripts/wsp.js @@ -0,0 +1,46 @@ +var wsp = { + messages: new WspMessager('#message-area'), + fileBrowser: new WspFileBrowser(), + dialogs: new WspDialogs() +}; + + +$(document).ready(function () { + $('.processing-dialog').click(function () { + wsp.dialogs.showProcessDialog(); + }); +}); + +//Toggle file select + Ctrl multiselect +$(document).on('click', '.element-container', function (e) { + if (e.ctrlKey) { + + $(this).toggleClass("selected-file"); + + } else { + + wsp.fileBrowser.clearAllSelectedItems(); + + wsp.fileBrowser.selectItem(this); + } + + wsp.fileBrowser.refreshDeletionBlock(); +}); + +//Double click file open +$(document).on('dblclick', '.element-container', function (e) { + wsp.fileBrowser.openItem(this); +}); + + +//Delete button click +$(document).on('click', '.file-deletion #delete-button', function (e) { + var dialogId = $(this).data('target'); + var buttonText = $(this).data('target-positive-button-text'); + var content = $(this).data('target-content'); + var title = $(this).data('target-title-text'); + + content = jQuery.validator.format(content, wsp.fileBrowser.getSelectedItemsCount()); + + wsp.dialogs.showConfirmDialog(title, content, buttonText, wsp.fileBrowser.deleteSelectedItems, dialogId); +}); \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Resources.Designer.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Resources.Designer.cs index 8c1b3158..8b375ced 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Resources.Designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Resources.Designer.cs @@ -69,6 +69,15 @@ namespace WebsitePanel.WebDavPortal.UI { } } + /// + /// Looks up a localized string similar to Cancel. + /// + public static string Cancel { + get { + return ResourceManager.GetString("Cancel", resourceCulture); + } + } + /// /// Looks up a localized string similar to Close. /// @@ -78,6 +87,42 @@ namespace WebsitePanel.WebDavPortal.UI { } } + /// + /// Looks up a localized string similar to Confirm. + /// + public static string Confirm { + get { + return ResourceManager.GetString("Confirm", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delete. + /// + public static string Delete { + get { + return ResourceManager.GetString("Delete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delete File?. + /// + public static string DeleteFileQuestion { + get { + return ResourceManager.GetString("DeleteFileQuestion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to delete {0} item(s)?. + /// + public static string DialogsContentConfrimFileDeletion { + get { + return ResourceManager.GetString("DialogsContentConfrimFileDeletion", resourceCulture); + } + } + /// /// Looks up a localized string similar to File Upload. /// @@ -96,6 +141,24 @@ namespace WebsitePanel.WebDavPortal.UI { } } + /// + /// Looks up a localized string similar to {0} items was removed.. + /// + public static string ItemsWasRemovedFormat { + get { + return ResourceManager.GetString("ItemsWasRemovedFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No files are selected.. + /// + public static string NoFilesAreSelected { + get { + return ResourceManager.GetString("NoFilesAreSelected", resourceCulture); + } + } + /// /// Looks up a localized string similar to Processing. /// @@ -122,5 +185,14 @@ namespace WebsitePanel.WebDavPortal.UI { return ResourceManager.GetString("Upload", resourceCulture); } } + + /// + /// Looks up a localized string similar to Yes. + /// + public static string Yes { + get { + return ResourceManager.GetString("Yes", resourceCulture); + } + } } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Resources.resx b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Resources.resx index 8329ece5..00e0624f 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Resources.resx +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Resources.resx @@ -120,15 +120,36 @@ Actions + + Cancel + Close + + Confirm + + + Delete + + + Delete File? + + + Are you sure you want to delete {0} item(s)? + File Upload Gb + + {0} items was removed. + + + No files are selected. + Processing @@ -138,4 +159,7 @@ Upload + + Yes + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Routes/FileSystemRouteNames.cs b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Routes/FileSystemRouteNames.cs index 8767815d..9732a57e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Routes/FileSystemRouteNames.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/UI/Routes/FileSystemRouteNames.cs @@ -12,5 +12,7 @@ namespace WebsitePanel.WebDavPortal.UI.Routes public const string ShowAdditionalContent = "ShowAdditionalContentRoute"; public const string UploadFile = "UplaodFIleRoute"; + + public const string DeleteFiles = "DeleteFilesRoute"; } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/FileSystem/ShowContent.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/FileSystem/ShowContent.cshtml index 2ffecc86..94e7d9c4 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/FileSystem/ShowContent.cshtml +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/FileSystem/ShowContent.cshtml @@ -12,12 +12,7 @@ var webDavManager = DependencyResolver.Current.GetService(); ViewBag.Title = WebDavAppConfigManager.Instance.ApplicationName; } -@Scripts.Render("~/bundles/jquery") -@Scripts.Render("~/bundles/appScripts") -
@if (Model != null && !string.IsNullOrEmpty(Model.Error)) @@ -37,12 +32,21 @@ else @elements[i] } + } + +
+ @if (Model.Permissions.HasFlag(WebDavPermissions.Write)) + { + + @Resources.FileUpload - if (Model.Permissions.HasFlag(WebDavPermissions.Write)) - { - @*@Resources.FileUpload*@ - - *@ }

+
@if (Model != null) { @@ -68,6 +72,13 @@ else
} +@section scripts{ + +} @section popups { @@ -93,4 +104,5 @@ else
@Html.Partial("_ProcessDialog", null) + @Html.Partial("_ConfirmDialog") } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/FileSystem/_ResoursePartial.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/FileSystem/_ResoursePartial.cshtml index 674917d1..bb65d42c 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/FileSystem/_ResoursePartial.cshtml +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/FileSystem/_ResoursePartial.cshtml @@ -17,12 +17,12 @@ { case FileOpenerType.OfficeOnline: isTargetBlank = true; - var pathPart = Model.Href.AbsolutePath.Replace("/" + WspContext.User.OrganizationId, ""); + var pathPart = Model.Href.AbsolutePath.Replace("/" + WspContext.User.OrganizationId, "").TrimStart('/'); href = string.Concat(Url.RouteUrl(FileSystemRouteNames.ShowOfficeOnlinePath, new { org = WspContext.User.OrganizationId, pathPart = "" }), pathPart); break; default: isTargetBlank = false; - href = Model.Href.AbsolutePath; + href = Model.Href.LocalPath; break; } @@ -39,17 +39,22 @@ }
- - + + +

@name

+ @if (showStatistic) {
- @percent% +

@percent%

@Math.Round(Convert.ToDecimal(resource.ContentLength) / 1024, 2) / @Math.Round(Convert.ToDecimal(resource.AllocatedSpace) / 1024, 2) @Resources.GigabyteShort

} + +
+
\ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/_ConfirmDialog.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/_ConfirmDialog.cshtml new file mode 100644 index 00000000..1711a807 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/_ConfirmDialog.cshtml @@ -0,0 +1,20 @@ +@using WebsitePanel.WebDavPortal.UI + diff --git a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/_Layout.cshtml b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/_Layout.cshtml index cd295597..7e4a94a3 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/_Layout.cshtml +++ b/WebsitePanel/Sources/WebsitePanel.WebDavPortal/Views/Shared/_Layout.cshtml @@ -1,9 +1,11 @@ -@using Ninject +@using System.Web.Script.Serialization +@using Ninject @using WebsitePanel.WebDav.Core @using WebsitePanel.WebDav.Core.Config @using WebsitePanel.WebDavPortal.DependencyInjection @using WebsitePanel.WebDavPortal.Models @using WebsitePanel.WebDavPortal.UI.Routes; +@model WebsitePanel.WebDavPortal.Models.Common.BaseModel @@ -16,7 +18,7 @@