diff --git a/src/Smartstore.Core/Checkout/Permissions.Checkout.cs b/src/Smartstore.Core/Checkout/Permissions.Checkout.cs index e12f14f887..19c0e2304a 100644 --- a/src/Smartstore.Core/Checkout/Permissions.Checkout.cs +++ b/src/Smartstore.Core/Checkout/Permissions.Checkout.cs @@ -83,6 +83,7 @@ public static class Cart { public const string Self = "cart"; public const string Read = "cart.read"; + public const string AccessOrders = "cart.accessorders"; public const string AccessShoppingCart = "cart.accessshoppingcart"; public const string AccessWishlist = "cart.accesswishlist"; diff --git a/src/Smartstore.Core/Migrations/SmartDbContextDataSeeder.cs b/src/Smartstore.Core/Migrations/SmartDbContextDataSeeder.cs deleted file mode 100644 index cb077ae290..0000000000 --- a/src/Smartstore.Core/Migrations/SmartDbContextDataSeeder.cs +++ /dev/null @@ -1,211 +0,0 @@ -using Smartstore.Core.Configuration; -using Smartstore.Data.Migrations; - -namespace Smartstore.Core.Data.Migrations -{ - public class SmartDbContextDataSeeder : IDataSeeder - { - public DataSeederStage Stage => DataSeederStage.Early; - public bool AbortOnFailure => false; - - public async Task SeedAsync(SmartDbContext context, CancellationToken cancelToken = default) - { - await context.MigrateSettingsAsync(builder => - { - builder.Delete("CustomerSettings.AvatarMaximumSizeBytes", "CatalogSettings.FileUploadMaximumSizeBytes"); - }); - - await context.MigrateLocaleResourcesAsync(MigrateLocaleResources); - await MigrateSettingsAsync(context, cancelToken); - } - - public async Task MigrateSettingsAsync(SmartDbContext db, CancellationToken cancelToken = default) - { - // ContentSlider: Replace old service in templates. - - var contentSliderTemplate = new[] - { - // Template1 - @"\r\n
\r\n\t
\r\n\t\t
\r\n\t\t\t

Slide-Title

\r\n\t\t\t

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

\r\n\t\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t
\r\n
\r\n", - // Template2 - @"\r\n
\r\n\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\t

Slide-Title

\r\n\t\t\t

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.

\r\n\t\t
\r\n\t
\r\n
\r\n", - // Template3 - @"\r\n
\r\n\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\t

Slide-Title

\r\n\t\t\t

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

\r\n\t\t
\r\n\t
\r\n
\r\n", - // Template4 - @"\r\n
\r\n\t
\r\n\t\t
\r\n\t\t\t
\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t
\r\n\t\t
\r\n\t\t\t
\r\n\t\t\t\t

Slide-Title

\r\n\t\t\t\t

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est .

\r\n\t\t\t
\r\n\t\t
\r\n\t
\r\n
\r\n", - // Template5 - @"\r\n
\r\n\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t
\r\n
\r\n", - // Template6 - @"\r\n
\r\n\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\t
\r\n
\r\n" - }; - - for (var i = 0; i < 6; i++) - { - var templateName = $"ContentSlider.Template{i + 1}"; - var template = await db.Settings - .Where(x => x.Name == templateName) - .FirstOrDefaultAsync(cancelToken); - - if (template != null) - { - db.Remove(template); - db.Settings.Add(new Setting - { - Name = templateName, - Value = contentSliderTemplate[i], - StoreId = 0 - }); - } - } - - await db.SaveChangesAsync(cancelToken); - } - - public void MigrateLocaleResources(LocaleResourcesBuilder builder) - { - builder.Delete( - "Account.ChangePassword.Errors.PasswordIsNotProvided", - "Common.Wait...", - "Topic.Button", - "Admin.Configuration.Settings.RewardPoints.Earning.Hint1", - "Admin.Configuration.Settings.RewardPoints.Earning.Hint2", - "Admin.Configuration.Settings.RewardPoints.Earning.Hint3", - "ShoppingCart.MaximumUploadedFileSize"); - - builder.AddOrUpdate("Admin.Report.MediaFilesSize", "Media size", "Mediengröße"); - builder.AddOrUpdate("Admin.Rules.FilterDescriptor.Affiliate", "Affiliate", "Partner"); - builder.AddOrUpdate("Admin.Rules.FilterDescriptor.Authentication", "Authentication", "Authentifizierung"); - - builder.AddOrUpdate("Admin.Customers.RemoveAffiliateAssignment", - "Remove assignment to affiliate", - "Zuordnung zum Partner entfernen"); - - builder.AddOrUpdate("Admin.Configuration.Settings.Order.MaxMessageOrderAgeInDays", - "Maximum order age for sending messages", - "Maximale Auftragsalter für den Nachrichtenversand", - "Specifies the maximum order age in days up to which to create and send messages. Set to 0 to always send messages.", - "Legt das maximale Auftragsalter in Tagen fest, bis zu dem Nachrichten erstellt und gesendet werden sollen. Setzen Sie diesen Wert auf 0, um Nachrichten immer zu versenden."); - - builder.AddOrUpdate("Admin.MessageTemplate.OrderTooOldForMessageInfo", - "The message \"{0}\" was not sent. The order {1} is too old ({2}).", - "Die Nachricht \"{0}\" wurde nicht gesendet. Der Auftrag {1} ist zu alt ({2})."); - - // Typo. - builder.AddOrUpdate("Admin.Configuration.Settings.ShoppingCart.ShowConfirmOrderLegalHint.Hint") - .Value("de", "Legt fest, ob rechtliche Hinweise in der Warenkorbübersicht auf der Bestellabschlussseite angezeigt werden. Dieser Text kann in den Sprachresourcen geändert werden."); - - builder.AddOrUpdate("Admin.Configuration.Settings.GeneralCommon.UseNativeNameInLanguageSelector", - "Display native language name in language selector", - "In der Sprachauswahl den Sprachnamen in der Landesprache anzeigen", - "Specifies whether the native language name should be displayed in the language selector. Otherwise, the name maintained in the backend is used.", - "Legt fest, ob in der Sprachauswahl die Sprachnamen in der nativen Landesprache angezeigt werden soll. Ansonsten wird der im Backend hinterlegte Name verwendet."); - - builder.AddOrUpdate("Common.PageNotFound", "The page does not exist.", "Die Seite existiert nicht."); - - builder.AddOrUpdate("Admin.GiftCards.Fields.Language", - "Language", - "Sprache", - "Specifies the language of the message content.", - "Legt die Sprache des Nachrichteninhalts fest."); - - builder.AddOrUpdate("RewardPoints.OrderAmount", "Order amount", "Bestellwert"); - builder.AddOrUpdate("RewardPoints.PointsForPurchasesInfo", - "For every {0} order amount {1} points are awarded.", - "Für je {0} Auftragswert werden {1} Punkte gewährt."); - - builder.AddOrUpdate("Common.Error.BotsNotPermitted", - "This process is not permitted for search engine queries (bots).", - "Dieser Vorgang ist für Suchmaschinenanfragen (Bots) nicht zulässig."); - - // ----- Conditional attributes review (begin) - builder.AddOrUpdate("Admin.Catalog.Products.ProductVariantAttributes.Attributes.Values.EditAttributeDetails", - "Edit attribute. Product: {0}", - "Attribut bearbeiten. Produkt: {0}"); - - builder.AddOrUpdate("Admin.Catalog.Attributes.ProductAttributes.OptionsSetsInfo", - "{0} option sets and {1} options", - "{0} Options-Sets und {1} Optionen"); - - builder.AddOrUpdate("Admin.Rules.ProductAttribute.OneCondition", - "Only show the attribute if at least {0} of the following rules are true.", - "Das Attribut nur anzeigen, wenn mindestens {0} der folgenden Regeln zutrifft."); - - builder.AddOrUpdate("Admin.Rules.ProductAttribute.AllConditions", - "Only show the attribute if {0} of the following rules are true.", - "Das Attribut nur anzeigen, wenn {0} der folgenden Regeln erfüllt sind."); - - - builder.AddOrUpdate("Admin.Catalog.Products.ProductVariantAttributes.EditOptions", - "Edit {0} options", - "{0} Optionen bearbeiten"); - - builder.AddOrUpdate("Admin.Catalog.Products.ProductVariantAttributes.EditRules", - "Edit {0} rules", - "{0} Regeln bearbeiten"); - - builder.AddOrUpdate("Admin.Catalog.Products.ProductVariantAttributes.EditOptionsAndRules", - "Edit {0} options and {1} rules", - "{0} Optionen und {1} Regeln bearbeiten"); - - - builder.AddOrUpdate("Admin.Rules.AddRuleWarning", "Please add a rule first.", "Bitte zuerst eine Regel hinzufügen."); - - builder.AddOrUpdate("Admin.Rules.AddCondition", "Add rule", "Regel hinzufügen"); - builder.AddOrUpdate("Admin.Rules.AllConditions", - "If {0} of the following rules are true.", - "Wenn {0} der folgenden Regeln erfüllt sind."); - - builder.AddOrUpdate("Admin.Rules.OneCondition", - "If at least {0} of the following rules are true.", - "Wenn mindestens {0} der folgenden Regeln zutrifft."); - - builder.AddOrUpdate("Admin.Rules.SaveConditions", "Save all rules", "Alle Regeln speichern"); - builder.AddOrUpdate("Admin.Rules.SaveToCreateConditions", - "Rules can only be created after saving.", - "Regeln können erst nach einem Speichern festgelegt werden."); - - builder.AddOrUpdate("Admin.Rules.TestConditions").Value("de", "Regeln {0} Testen {1}"); - - builder.AddOrUpdate("Admin.Rules.EditRuleSet", "Edit rule set", "Regelsatz bearbeiten"); - builder.AddOrUpdate("Admin.Rules.OpenRuleSet", "Open rule set", "Regelsatz öffnen"); - builder.Delete( - "Admin.Rules.EditRule", - "Admin.Rules.OpenRule", - "Admin.Catalog.Products.ProductVariantAttributes.Attributes.Values.ViewLink"); - // ----- Conditional attributes review (end) - - builder.AddOrUpdate("Admin.Configuration.Settings.CustomerUser.MaxAvatarFileSize", - "Maximum avatar size", - "Maximale Avatar-Größe", - "Specifies the maximum file size of an avatar (in KB). The default is 10,240 (10 MB).", - "Legt die maximale Dateigröße eines Avatar in KB fest. Der Standardwert ist 10.240 (10 MB)."); - - builder.AddOrUpdate("Admin.Configuration.Settings.GeneralCommon.ShowOnPasswordRecoveryPage", - "Show on password recovery page", - "Auf der Seite zur Passwort-Wiederherstellung anzeigen"); - - builder.Delete("Admin.ContentManagement.Topics.Validation.NoWhiteSpace"); - - builder.AddOrUpdate("Admin.Common.HtmlId.NoWhiteSpace", - "Spaces are invalid for the HTML attribute 'id'.", - "Leerzeichen sind für das HTML-Attribut 'id' ungültig."); - - builder.AddOrUpdate("CookieManager.Dialog.AdUserDataConsent.Heading", - "Marketing", - "Marketing"); - - builder.AddOrUpdate("CookieManager.Dialog.AdUserDataConsent.Intro", - "With your consent, our advertising partners can set cookies to create an interest profile for you so that we can offer you targeted advertising. For this purpose, we pass on an identifier unique to your customer account to these services.", - "Unsere Werbepartner können mit Ihrer Einwilligung Cookies setzen, um ein Interessenprofil für Sie zu erstellen, damit wir Ihnen gezielt Werbung anbieten können. Dazu geben wir eine für Ihr Kundenkonto eindeutige Kennung an diese Dienste weiter. "); - - builder.AddOrUpdate("CookieManager.Dialog.AdPersonalizationConsent.Heading", - "Personalization", - "Personalisierung"); - - builder.AddOrUpdate("CookieManager.Dialog.AdPersonalizationConsent.Intro", - "Consent to personalisation enables us to offer enhanced functionality and personalisation. They can be set by us or by third-party providers whose services we use on our pages.", - "Die Zustimmung zur Personalisierung ermöglicht es uns, erweiterte Funktionalität und Personalisierung anzubieten. Sie können von uns oder von Drittanbietern gesetzt werden, deren Dienste wir auf unseren Seiten nutzen."); - - } - } -} \ No newline at end of file diff --git a/src/Smartstore.Core/Platform/Security/Services/StandardPermissionProvider.cs b/src/Smartstore.Core/Platform/Security/Services/StandardPermissionProvider.cs index 0aacaacdb6..2354d8ddd1 100644 --- a/src/Smartstore.Core/Platform/Security/Services/StandardPermissionProvider.cs +++ b/src/Smartstore.Core/Platform/Security/Services/StandardPermissionProvider.cs @@ -41,6 +41,7 @@ public virtual IEnumerable GetDefaultPermissions() PermissionRecords = new[] { new PermissionRecord { SystemName = Permissions.Catalog.DisplayPrice }, + new PermissionRecord { SystemName = Permissions.Cart.AccessOrders }, new PermissionRecord { SystemName = Permissions.Cart.AccessShoppingCart }, new PermissionRecord { SystemName = Permissions.Cart.AccessWishlist }, new PermissionRecord { SystemName = Permissions.System.AccessShop } @@ -52,6 +53,7 @@ public virtual IEnumerable GetDefaultPermissions() PermissionRecords = new[] { new PermissionRecord { SystemName = Permissions.Catalog.DisplayPrice }, + new PermissionRecord { SystemName = Permissions.Cart.AccessOrders }, new PermissionRecord { SystemName = Permissions.Cart.AccessShoppingCart }, new PermissionRecord { SystemName = Permissions.Cart.AccessWishlist }, new PermissionRecord { SystemName = Permissions.System.AccessShop } @@ -63,6 +65,7 @@ public virtual IEnumerable GetDefaultPermissions() PermissionRecords = new[] { new PermissionRecord { SystemName = Permissions.Catalog.DisplayPrice }, + new PermissionRecord { SystemName = Permissions.Cart.AccessOrders }, new PermissionRecord { SystemName = Permissions.Cart.AccessShoppingCart }, new PermissionRecord { SystemName = Permissions.Cart.AccessWishlist }, new PermissionRecord { SystemName = Permissions.System.AccessShop } diff --git a/src/Smartstore.Web/Components/AccountDropdownViewComponent.cs b/src/Smartstore.Web/Components/AccountDropdownViewComponent.cs index d59e58ae68..dfacdc7a0b 100644 --- a/src/Smartstore.Web/Components/AccountDropdownViewComponent.cs +++ b/src/Smartstore.Web/Components/AccountDropdownViewComponent.cs @@ -18,6 +18,7 @@ public async Task InvokeAsync() DisplayAdminLink = await Services.Permissions.AuthorizeAsync(Permissions.System.AccessBackend), ShoppingCartEnabled = await Services.Permissions.AuthorizeAsync(Permissions.Cart.AccessShoppingCart), WishlistEnabled = await Services.Permissions.AuthorizeAsync(Permissions.Cart.AccessWishlist), + OrdersEnabled = await Services.Permissions.AuthorizeAsync(Permissions.Cart.AccessOrders), //ShoppingCartItems = await Services.DbContext.ShoppingCartItems.CountCartItemsAsync(customer, ShoppingCartType.ShoppingCart, Services.StoreContext.CurrentStore.Id), //WishlistItems = await Services.DbContext.ShoppingCartItems.CountCartItemsAsync(customer, ShoppingCartType.Wishlist, Services.StoreContext.CurrentStore.Id) }; @@ -29,12 +30,15 @@ public async Task InvokeAsync() .Text(T("Account.MyAccount")) .AsItem()); - model.MenuItems.Add(new MenuItem().ToBuilder() - .Action("Orders", "Customer") - .LinkHtmlAttributes(new { @class = "dropdown-item", rel = "nofollow" }) - .Icon("fal fa-file-lines fa-fw") - .Text(T("Account.MyOrders")) - .AsItem()); + if (model.OrdersEnabled) + { + model.MenuItems.Add(new MenuItem().ToBuilder() + .Action("Orders", "Customer") + .LinkHtmlAttributes(new { @class = "dropdown-item", rel = "nofollow" }) + .Icon("fal fa-file-lines fa-fw") + .Text(T("Account.MyOrders")) + .AsItem()); + } if (model.DisplayAdminLink) { diff --git a/src/Smartstore.Web/Controllers/CustomerController.cs b/src/Smartstore.Web/Controllers/CustomerController.cs index fbb5fe6aae..c37cd0d15a 100644 --- a/src/Smartstore.Web/Controllers/CustomerController.cs +++ b/src/Smartstore.Web/Controllers/CustomerController.cs @@ -494,6 +494,11 @@ public async Task Orders(int? page, int? recurringPaymentsPage) return ChallengeOrForbid(); } + if (!await Services.Permissions.AuthorizeAsync(Permissions.Cart.AccessOrders)) + { + return RedirectToRoute("Homepage"); + } + var ordersPageIndex = Math.Max((page ?? 0) - 1, 0); var rpPageIndex = Math.Max((recurringPaymentsPage ?? 0) - 1, 0); diff --git a/src/Smartstore.Web/Infrastructure/Menus/MyAccountMenu.cs b/src/Smartstore.Web/Infrastructure/Menus/MyAccountMenu.cs index e062feab81..f6cb2443cf 100644 --- a/src/Smartstore.Web/Infrastructure/Menus/MyAccountMenu.cs +++ b/src/Smartstore.Web/Infrastructure/Menus/MyAccountMenu.cs @@ -3,6 +3,7 @@ using Smartstore.Core.Content.Menus; using Smartstore.Core.Identity; using Smartstore.Core.Localization; +using Smartstore.Core.Security; namespace Smartstore.Web.Infrastructure { @@ -110,16 +111,20 @@ protected virtual async Task> BuildAsync() Icon = "fal fa-address-book", ActionName = "Addresses", ControllerName = "Customer" - }, - new MenuItem + } + }); + + if (await _services.Permissions.AuthorizeAsync(Permissions.Cart.AccessOrders)) + { + root.Append(new MenuItem { Id = "orders", Text = T("Account.CustomerOrders"), Icon = "fal fa-file-lines", ActionName = "Orders", ControllerName = "Customer" - } - }); + }); + } if (_orderSettings.ReturnRequestsEnabled) { diff --git a/src/Smartstore.Web/Models/Common/AccountDropdownModel.cs b/src/Smartstore.Web/Models/Common/AccountDropdownModel.cs index 6371d4461d..599cdd83a0 100644 --- a/src/Smartstore.Web/Models/Common/AccountDropdownModel.cs +++ b/src/Smartstore.Web/Models/Common/AccountDropdownModel.cs @@ -10,6 +10,7 @@ public partial class AccountDropdownModel : EntityModelBase public bool ShoppingCartEnabled { get; set; } public int ShoppingCartItems { get; set; } public bool WishlistEnabled { get; set; } + public bool OrdersEnabled { get; set; } public int WishlistItems { get; set; } public List MenuItems { get; } = new();