(refactor): frontend and backend pairing started

This commit is contained in:
Maksym Sadovnychyy 2023-03-26 22:21:09 +02:00
parent b4d484bf51
commit cdaabb4cd3
109 changed files with 1322 additions and 470 deletions

View File

@ -1 +1,2 @@
BROWSER=none
REACT_APP_SITEID=404c8232-9048-4519-bfba-6e78dc7005ca

View File

@ -41,6 +41,7 @@ export interface GetShopCartItemResponseModel {
// Static content response model
export interface GetContentResponseModel extends ResponseModel {
siteName: string,
siteUrl: string,

View File

@ -22,7 +22,11 @@ type KnownAction = RequestAction | ReceiveAction
export const actionCreators = {
requestBlogFeatured: (props?: GetBlogFeaturedRequestModel): AppThunkAction<KnownAction> => (dispatch, getState) => {
Get<Promise<GetBlogFeaturedResponseModel>>('https://localhost:7151/api/BlogFeatured', props?.pathParams, props?.searchParams)
const locale = getState().content?.localization.locale
const searchParams = {...props?.pathParams, locale}
Get<Promise<GetBlogFeaturedResponseModel>>(`https://localhost:7151/api/BlogItems/Featured/${process.env.REACT_APP_SITEID}`, props?.pathParams, searchParams)
.then(response => response)
.then(data => {
if(data)

View File

@ -23,7 +23,7 @@ type KnownAction = RequestAction | ReceiveAction;
export const actionCreators = {
requestContent: (props?: GetContentRequestModel): AppThunkAction<KnownAction> => (dispatch, getState) => {
Get<Promise<GetContentResponseModel>>('https://localhost:7151/api/Content/404c8232-9048-4519-bfba-6e78dc7005ca', props?.pathParams, props?.searchParams)
Get<Promise<GetContentResponseModel>>(`https://localhost:7151/api/Content/${process.env.REACT_APP_SITEID}`, props?.pathParams, props?.searchParams)
.then(response => response)
.then((data) => {
if(data) {

View File

@ -9,7 +9,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
</ItemGroup>
<ItemGroup>

View File

@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.10" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.25.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="7.0.4" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.27.0" />
</ItemGroup>

View File

@ -16,6 +16,7 @@ namespace DataProviders.Collections
(List<BlogDocument>?, IDomainResult) GetBySlugs(Guid siteId, List<string> slugs);
(List<BlogDocument>?, IDomainResult) GetMany(Guid siteId, List<Guid> blogIds);
(List<BlogDocument>?, IDomainResult) GetAll(Guid siteId, int skip, int take);
(int?, IDomainResult) Count(Guid siteId);
(Guid?, IDomainResult) Update(BlogDocument blogItem);
IDomainResult Delete(Guid id);
IDomainResult DeleteMany(Guid siteId, List<Guid> blogIds);
@ -61,6 +62,11 @@ namespace DataProviders.Collections
public (List<BlogDocument>?, IDomainResult) GetAll(Guid siteId, int skip, int take) =>
GetWithPredicate(x => x.SiteId == siteId, x => x);
public (int?, IDomainResult) Count(Guid siteId) {
var (list, result) = GetWithPredicate(x => x.SiteId == siteId, x => x.Id);
return (list?.Count, result);
}
public (Guid?, IDomainResult) Update(BlogDocument blogItem) =>
UpdateWithPredicate(blogItem, x => x.Id == blogItem.Id);

View File

@ -20,6 +20,7 @@ namespace DataProviders.Collections
(Category?, IDomainResult) GetBySlug(Guid siteId, string slug);
(List<Category>?, IDomainResult) GetBySlugs(Guid siteId, List<string> slugs);
(List<Category>?, IDomainResult) GetAll(Guid siteId);
(int?, IDomainResult) Count(Guid siteId);
(Guid?, IDomainResult) Update(Category obj);
IDomainResult Delete(Guid id);
IDomainResult DeleteAll(Guid siteId);
@ -81,6 +82,11 @@ namespace DataProviders.Collections
public (List<Category>?, IDomainResult) GetAll(Guid siteId) =>
GetWithPredicate(x => x.SiteId == siteId, x => x);
public (int?, IDomainResult) Count(Guid siteId) {
var (list, result) = GetWithPredicate(x => x.SiteId == siteId, x => x.Id);
return (list?.Count, result);
}
public (Guid?, IDomainResult) Update(Category obj) =>
UpdateWithPredicate(obj, x => x.Id == obj.Id);

View File

@ -7,11 +7,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DomainResult.Common" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="MongoDB.Driver" Version="2.18.0" />
<PackageReference Include="MongoDB.Driver.GridFS" Version="2.18.0" />
<PackageReference Include="DomainResult.Common" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="MongoDB.Driver" Version="2.19.0" />
<PackageReference Include="MongoDB.Driver.GridFS" Version="2.19.0" />
</ItemGroup>
<ItemGroup>

View File

@ -121,6 +121,9 @@ namespace DataProviders
if (!BsonClassMap.IsClassMapRegistered(typeof(Localization))) {
BsonClassMap.RegisterClassMap<Localization>(cm => {
cm.AutoMap();
cm.GetMemberMap(c => c.Locale)
.SetSerializer(new EnumerationSerializer<Locales>());
});
}
@ -328,6 +331,7 @@ namespace DataProviders
#region Content
if (!BsonClassMap.IsClassMapRegistered(typeof(ContentDocument))) {
BsonClassMap.RegisterClassMap<ContentDocument>(cm => {
cm.AutoMap();

View File

@ -1,6 +1,5 @@
using CryptoProvider;
using DomainObjects.Abstractions;
using DomainObjects.Documents.Sites;
using DomainObjects.Enumerations;
namespace DomainObjects.Documents.Users;

View File

@ -17,6 +17,7 @@ public class PostItemL10n : DomainObjectBase<PostItemL10n> {
public override int GetHashCode() {
unchecked {
int hash = 17;
hash = hash * 23 + Locale.GetHashCode();
hash = hash * 23 + Slug.GetHashCode();
hash = hash * 23 + Description.GetHashCode();
@ -24,7 +25,10 @@ public class PostItemL10n : DomainObjectBase<PostItemL10n> {
hash = hash * 23 + Text.GetHashCode();
hash = hash * 23 + TextFormat.GetHashCode();
hash = hash * 23 + ShortText.GetHashCode();
hash = hash * 23 + Badges.Sum(x => x.GetHashCode());
if(Badges != null)
hash = hash * 23 + Badges.GetHashCode();
return hash;
}
}

View File

@ -1,4 +1,5 @@
using DomainObjects.Abstractions;
using DomainObjects.Enumerations;
namespace DomainObjects;
@ -6,7 +7,7 @@ public class Localization : DomainObjectBase<Localization> {
public string? TimeZone { get; set; }
public string? Locale { get; set; }
public Locales Locale { get; set; }
public string? DateFormat { get; set; }

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MailKit" Version="3.4.2" />
<PackageReference Include="MailKit" Version="3.6.0" />
</ItemGroup>
</Project>

View File

@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DomainResult.Common" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="DomainResult.Common" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="nClam" Version="7.0.0" />
</ItemGroup>

View File

@ -7,11 +7,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DomainResult.Common" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" />
<PackageReference Include="DomainResult.Common" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta0013" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.0" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
</ItemGroup>

View File

@ -10,7 +10,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="Yarp.ReverseProxy" Version="1.1.1" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
<PackageReference Include="Yarp.ReverseProxy" Version="2.0.0" />
</ItemGroup>
</Project>

View File

@ -8,14 +8,14 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="MongoDB.Driver" Version="2.18.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="MongoDB.Driver" Version="2.19.0" />
<PackageReference Include="xunit" Version="2.4.2" />
</ItemGroup>

View File

@ -9,15 +9,15 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PackageReference Include="coverlet.collector" Version="3.2.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>

View File

@ -1,11 +1,13 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
namespace WeatherForecast.Controllers.Abstractions {
/// <summary>
///
/// </summary>
[ApiController]
public class AuthorizationControllerBase : ControllerBase {
private readonly IAuthorizationService _authorizationService;
@ -24,12 +26,13 @@ namespace WeatherForecast.Controllers.Abstractions {
///
/// </summary>
/// <typeparam name="TRequirement"></typeparam>
/// <param name="user"></param>
/// <param name="requirement"></param>
/// <param name="businessLogic"></param>
/// <returns></returns>
protected async Task<IActionResult> AuthorizeAsync<TRequirement>(TRequirement requirement, Func<IActionResult> businessLogic)
protected async Task<IActionResult> AuthorizeAsync<TRequirement>(ClaimsPrincipal user, TRequirement requirement, Func<IActionResult> businessLogic)
where TRequirement : IAuthorizationRequirement {
var authorizationResult = await _authorizationService.AuthorizeAsync(User, null, requirement);
var authorizationResult = await _authorizationService.AuthorizeAsync(user, null, requirement);
if (authorizationResult.Succeeded) {
return businessLogic();
@ -43,13 +46,14 @@ namespace WeatherForecast.Controllers.Abstractions {
/// </summary>
/// <typeparam name="TRequirement"></typeparam>
/// <typeparam name="TResource"></typeparam>
/// <param name="user"></param>
/// <param name="requirement"></param>
/// <param name="resource"></param>
/// <param name="businessLogic"></param>
/// <returns></returns>
public async Task<IActionResult> AuthorizeAsync<TRequirement, TResource>(TRequirement requirement, TResource resource, Func<IActionResult> businessLogic)
public async Task<IActionResult> AuthorizeAsync<TRequirement, TResource>(ClaimsPrincipal user, TRequirement requirement, TResource resource, Func<IActionResult> businessLogic)
where TRequirement : IAuthorizationRequirement {
var authorizationResult = await _authorizationService.AuthorizeAsync(User, resource, requirement);
var authorizationResult = await _authorizationService.AuthorizeAsync(user, resource, requirement);
if (authorizationResult.Succeeded) {
return businessLogic();

View File

@ -15,7 +15,6 @@ namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class AccountController : AuthorizationControllerBase {
@ -111,7 +110,7 @@ public class AccountController : AuthorizationControllerBase {
if (!getUserResult.IsSuccess || user == null)
return BadRequest();
return await AuthorizeAsync(new PasswordChangeRequirement(CrudActions.Update,
return await AuthorizeAsync(User, new PasswordChangeRequirement(CrudActions.Update,
requestData.OldPassword
), user, () => {
var result = _accountService.PasswordChange(user, requestData);

View File

@ -12,13 +12,13 @@ using DataProviders.Collections;
using DomainObjects.Documents.Users;
using WeatherForecast.Controllers.Abstractions;
using DomainObjects.Documents.Posts;
namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class BlogItemController : AuthorizationControllerBase {
@ -52,13 +52,13 @@ public class BlogItemController : AuthorizationControllerBase {
var blogItem = requestData.ToDomainObject(siteId, userId);
return await AuthorizeAsync(new BlogAuthorizationRequirement(CrudActions.Create, new List<BlogRole> {
return await AuthorizeAsync(User, new BlogAuthorizationRequirement(CrudActions.Create, new List<BlogRole> {
new BlogRole(Roles.Admin),
new BlogRole(Roles.Editor),
new BlogRole(Roles.Author) { OwnOnly = true },
new BlogRole(Roles.Contributor) { OwnOnly = true },
new BlogRole(Roles.ShopManager)
}), blogItem, () => {
}), new List<BlogDocument> { blogItem }, () => {
var result = _blogItemService.Post(blogItem);
return result.ToActionResult();
});
@ -79,13 +79,13 @@ public class BlogItemController : AuthorizationControllerBase {
if (!getBlogItemResult.IsSuccess || blogItem == null)
return getBlogItemResult.ToActionResult();
return await AuthorizeAsync(new BlogAuthorizationRequirement(CrudActions.Read, new List<BlogRole> {
return await AuthorizeAsync(User, new BlogAuthorizationRequirement(CrudActions.Read, new List<BlogRole> {
new BlogRole(Roles.Admin),
new BlogRole(Roles.Editor),
new BlogRole(Roles.Author) { OwnOnly = true },
new BlogRole(Roles.Contributor) { OwnOnly = true },
new BlogRole(Roles.ShopManager)
}), blogItem, () => {
}), new List<BlogDocument> { blogItem }, () => {
var result = _blogItemService.Get(blogItem);
return result.ToActionResult();
});
@ -123,13 +123,13 @@ public class BlogItemController : AuthorizationControllerBase {
newBlogItem.Created = blogItem.Created;
newBlogItem.Categories = blogItem.Categories;
return await AuthorizeAsync(new BlogAuthorizationRequirement(CrudActions.Update, new List<BlogRole> {
return await AuthorizeAsync(User, new BlogAuthorizationRequirement(CrudActions.Update, new List<BlogRole> {
new BlogRole(Roles.Admin),
new BlogRole(Roles.Editor),
new BlogRole(Roles.Author) { OwnOnly = true },
new BlogRole(Roles.Contributor) { OwnOnly = true, DenyPublished = true },
new BlogRole(Roles.ShopManager)
}), blogItem, () => {
}), new List<BlogDocument> { blogItem }, () => {
var result = _blogItemService.Update(newBlogItem);
return result.ToActionResult();
});
@ -149,13 +149,13 @@ public class BlogItemController : AuthorizationControllerBase {
if (!getBlogItemResult.IsSuccess || blogItem == null)
return getBlogItemResult.ToActionResult();
return await AuthorizeAsync(new BlogAuthorizationRequirement(CrudActions.Delete, new List<BlogRole> {
return await AuthorizeAsync(User, new BlogAuthorizationRequirement(CrudActions.Delete, new List<BlogRole> {
new BlogRole(Roles.Admin),
new BlogRole(Roles.Editor),
new BlogRole(Roles.Author) { OwnOnly = true },
new BlogRole(Roles.Contributor) { OwnOnly = true, DenyPublished = true },
new BlogRole(Roles.ShopManager)
}), blogItem, () => {
}), new List<BlogDocument> { blogItem }, () => {
var result = _blogItemService.Delete(blogItem);
return result.ToActionResult();
});

View File

@ -10,10 +10,11 @@ namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class BlogItemsController : ControllerBase {
private const string _featured = "Featured";
private readonly IBlogItemsService _blogItemsService;
/// <summary>
@ -37,4 +38,16 @@ public class BlogItemsController : ControllerBase {
var result = _blogItemsService.Get(siteId, requestData);
return result.ToActionResult();
}
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpGet($"{_featured}/{{siteId}}")]
public IActionResult GetFeatured([FromRoute] Guid siteId, [FromQuery] GetBlogItemsLocalizedRequestModel requestData) {
var result = _blogItemsService.Get(siteId, requestData);
return result.ToActionResult();
}
}

View File

@ -6,19 +6,18 @@ using DomainResults.Mvc;
using WeatherForecast.Services;
using WeatherForecast.Policies;
using Core.Enumerations;
using WeatherForecast.Models.Category.Requests;
using WeatherForecast.Models.CategoryItem.Requests;
using DomainObjects.Documents.Users;
using WeatherForecast.Controllers.Abstractions;
using DataProviders.Collections;
using DomainObjects.Enumerations;
using WeatherForecast.Models.Categories.Requests;
namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class CategoryItemController : AuthorizationControllerBase {
@ -54,7 +53,7 @@ public class CategoryItemController : AuthorizationControllerBase {
var category = requestData.ToDomainObject(siteId);
return await AuthorizeAsync(new CategoryAuthorizationRequirement(CrudActions.Create, new List<CategoryRole> {
return await AuthorizeAsync(User, new CategoryAuthorizationRequirement(CrudActions.Create, new List<CategoryRole> {
new CategoryRole(Roles.Admin),
new CategoryRole(Roles.Editor),
new CategoryRole(Roles.ShopManager)
@ -64,28 +63,6 @@ public class CategoryItemController : AuthorizationControllerBase {
});
}
#region Authless methods
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="requestData"></param>
[HttpGet("{siteId}")]
public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] GetCategoryItemSlugRequestModel requestData) {
var (category, getCategoryResult) = _categoryDataProvider.GetBySlug(siteId, requestData.Slug);
if (!getCategoryResult.IsSuccess || category == null)
return getCategoryResult.ToActionResult();
var locale = category.L10n.SingleOrDefault(x => x.Slug == requestData.Slug)?.Locale ?? Locales.Us;
var result = _categoryItemService.Get(category, locale);
return result.ToActionResult();
}
#endregion
/// <summary>
/// Returns full object
/// Can Admin, Editor, Author, Contributor, Shop manager
@ -100,7 +77,7 @@ public class CategoryItemController : AuthorizationControllerBase {
if (!result.IsSuccess || category == null)
return result.ToActionResult();
return await AuthorizeAsync(new CategoryAuthorizationRequirement(CrudActions.Read, new List<CategoryRole> {
return await AuthorizeAsync(User, new CategoryAuthorizationRequirement(CrudActions.Read, new List<CategoryRole> {
new CategoryRole(Roles.Admin),
new CategoryRole(Roles.Editor),
new CategoryRole(Roles.Author),
@ -112,6 +89,24 @@ public class CategoryItemController : AuthorizationControllerBase {
});
}
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="requestData"></param>
[HttpGet("{siteId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetCategoryItemLocalizedRequestModel requestData) {
var (category, getCategoryResult) = _categoryDataProvider.GetBySlug(siteId, requestData.Slug);
if (!getCategoryResult.IsSuccess || category == null)
return getCategoryResult.ToActionResult();
var locale = category.L10n.SingleOrDefault(x => x.Slug == requestData.Slug)?.Locale ?? Locales.Us;
var result = _categoryItemService.Get(category, locale);
return result.ToActionResult();
}
/// <summary>
/// Can Admin, Editor, Shop manager
/// </summary>
@ -124,7 +119,7 @@ public class CategoryItemController : AuthorizationControllerBase {
var category = requestData.ToDomainObject(siteId, categoryId);
return await AuthorizeAsync(new CategoryAuthorizationRequirement(CrudActions.Update, new List<CategoryRole> {
return await AuthorizeAsync(User, new CategoryAuthorizationRequirement(CrudActions.Update, new List<CategoryRole> {
new CategoryRole(Roles.Admin),
new CategoryRole(Roles.Editor),
new CategoryRole(Roles.ShopManager)
@ -143,7 +138,7 @@ public class CategoryItemController : AuthorizationControllerBase {
[HttpDelete("{siteId}/{categoryId}")]
public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid categoryId) {
return await AuthorizeAsync(new CategoryAuthorizationRequirement(CrudActions.Delete, new List<CategoryRole> {
return await AuthorizeAsync(User, new CategoryAuthorizationRequirement(CrudActions.Delete, new List<CategoryRole> {
new CategoryRole(Roles.Admin)
}), () => {
var result = _categoryItemService.Delete(siteId, categoryId);

View File

@ -4,30 +4,31 @@ using Microsoft.AspNetCore.Authorization;
using DomainResults.Mvc;
using WeatherForecast.Services;
using WeatherForecast.Models.CategoryItem.Requests;
using WeatherForecast.Models.Cetegories.Requests;
using WeatherForecast.Controllers.Abstractions;
namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class CategoryItemsController : ControllerBase {
public class CategoryItemsController : AuthorizationControllerBase {
private readonly ICategoryItemsService _categoryItemsService;
/// <summary>
///
/// </summary>
/// <param name="authorizationService"></param>
/// <param name="categoryItemsService"></param>
public CategoryItemsController(
IAuthorizationService authorizationService,
ICategoryItemsService categoryItemsService
) {
) : base (authorizationService) {
_categoryItemsService = categoryItemsService;
}
#region Authless methods
/// <summary>
///
/// </summary>
@ -35,10 +36,9 @@ public class CategoryItemsController : ControllerBase {
/// <param name="reuestData"></param>
/// <returns></returns>
[HttpGet("{siteId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetCategoryItemsRequestModel reuestData) {
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetCategoryItemsLocalizedRequestModel reuestData) {
var result = _categoryItemsService.Get(siteId, reuestData);
return result.ToActionResult();
}
#endregion
}

View File

@ -5,25 +5,27 @@ using DomainResults.Mvc;
using WeatherForecast.Services;
using WeatherForecast.Models.Content.Requests;
using WeatherForecast.Controllers.Abstractions;
namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ContentController : ControllerBase {
public class ContentController : AuthorizationControllerBase {
private readonly IContentService _contentService;
/// <summary>
///
/// </summary>
/// <param name="authorizationService"></param>
/// <param name="contentService"></param>
public ContentController(
IAuthorizationService authorizationService,
IContentService contentService
) {
) : base (authorizationService) {
_contentService = contentService;
}

View File

@ -16,7 +16,6 @@ namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[AllowAnonymous]
[Route("api/[controller]")]
public class DkimController : AuthorizationControllerBase {
@ -55,7 +54,7 @@ public class DkimController : AuthorizationControllerBase {
var newFile = new BucketFile(Guid.NewGuid(), siteId, formFile.FileName, ms.ToArray(), formFile.ContentType);
return await AuthorizeAsync(new DkimAuthorisationRequirement(CrudActions.Create, new List<DkimRole> {
return await AuthorizeAsync(User, new DkimAuthorisationRequirement(CrudActions.Create, new List<DkimRole> {
new DkimRole(Roles.Admin)
}), newFile, () => {
var result = _dkimService.Post(newFile);
@ -76,7 +75,7 @@ public class DkimController : AuthorizationControllerBase {
if (!fileDownloadResult.IsSuccess || file == null)
return fileDownloadResult.ToActionResult();
return await AuthorizeAsync(new DkimAuthorisationRequirement(CrudActions.Delete, new List<DkimRole> {
return await AuthorizeAsync(User, new DkimAuthorisationRequirement(CrudActions.Delete, new List<DkimRole> {
new DkimRole(Roles.Admin)
}), file, () => {
var result = _dkimService.Delete(siteId, fileId);

View File

@ -17,7 +17,6 @@ namespace WeatherForecast.Controllers;
///
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class ImageController : AuthorizationControllerBase {
private readonly IImageBucketDataProvider _imageBucketDataProvider;
@ -77,7 +76,7 @@ public class ImageController : AuthorizationControllerBase {
if (userId != null)
newFile.UserId = userId;
return await AuthorizeAsync(new ImageAuthorisationRequirement(CrudActions.Create, new List<ImageRole> {
return await AuthorizeAsync(User, new ImageAuthorisationRequirement(CrudActions.Create, new List<ImageRole> {
new ImageRole(Roles.Admin),
new ImageRole(Roles.Editor),
new ImageRole(Roles.Author) { OwnOnly = true },
@ -109,7 +108,7 @@ public class ImageController : AuthorizationControllerBase {
if (!result.IsSuccess || file == null)
return result.ToActionResult();
return await AuthorizeAsync(new ImageAuthorisationRequirement(CrudActions.Read, new List<ImageRole> {
return await AuthorizeAsync(User, new ImageAuthorisationRequirement(CrudActions.Read, new List<ImageRole> {
new ImageRole(Roles.Admin),
new ImageRole(Roles.Editor),
new ImageRole(Roles.Author) { OwnOnly = true },
@ -195,7 +194,7 @@ public class ImageController : AuthorizationControllerBase {
if(userId != null)
newFile.UserId = userId;
return await AuthorizeAsync(new ImageAuthorisationRequirement(CrudActions.Update, new List<ImageRole> {
return await AuthorizeAsync(User, new ImageAuthorisationRequirement(CrudActions.Update, new List<ImageRole> {
new ImageRole(Roles.Admin),
new ImageRole(Roles.Editor),
new ImageRole(Roles.Author) { OwnOnly = true },
@ -238,7 +237,7 @@ public class ImageController : AuthorizationControllerBase {
if (!fileDownloadResult.IsSuccess || file == null)
return fileDownloadResult.ToActionResult();
return await AuthorizeAsync(new ImageAuthorisationRequirement(CrudActions.Delete, new List<ImageRole> {
return await AuthorizeAsync(User, new ImageAuthorisationRequirement(CrudActions.Delete, new List<ImageRole> {
new ImageRole(Roles.Admin),
new ImageRole(Roles.Editor),
new ImageRole(Roles.Author) { OwnOnly = true },

View File

@ -14,7 +14,6 @@ namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[AllowAnonymous]
[Route("api/[controller]")]
public class ImagesController : AuthorizationControllerBase {
@ -64,7 +63,7 @@ public class ImagesController : AuthorizationControllerBase {
return newFile;
}).ToList();
return await AuthorizeAsync(new ImageAuthorisationRequirement(CrudActions.Create, new List<ImageRole> {
return await AuthorizeAsync(User, new ImageAuthorisationRequirement(CrudActions.Create, new List<ImageRole> {
new ImageRole(Roles.Admin),
new ImageRole(Roles.Editor),
new ImageRole(Roles.Author) { OwnOnly = true },

View File

@ -1,6 +1,8 @@
using DomainResults.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WeatherForecast.Controllers.Abstractions;
using WeatherForecast.Models.Initialization.Requests;
using WeatherForecast.Services;
@ -10,18 +12,19 @@ namespace WeatherForecast.Controllers;
///
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class InitializationController : ControllerBase {
public class InitializationController : AuthorizationControllerBase {
private readonly IInitializationService _initializationService;
/// <summary>
///
/// </summary>
/// <param name="authorizationService"></param>
/// <param name="initializationService"></param>
public InitializationController(
IAuthorizationService authorizationService,
IInitializationService initializationService
) {
) : base(authorizationService) {
_initializationService = initializationService;
}

View File

@ -17,7 +17,6 @@ namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[AllowAnonymous]
[Route("api/[controller]")]
public class ShopCartItemController : AuthorizationControllerBase {
@ -50,7 +49,7 @@ public class ShopCartItemController : AuthorizationControllerBase {
[HttpPost("{siteId}/{userId}/{sku}")]
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] string sku, [FromBody] PostShopCartItemRequestModel requestData) {
return await AuthorizeAsync(new ShopCartAuthorizationRequirement(CrudActions.Create), () => {
return await AuthorizeAsync(User, new ShopCartAuthorizationRequirement(CrudActions.Create), () => {
var result = _shopCartItemService.Post(siteId, userId, sku, requestData);
return result.ToActionResult();
});
@ -65,13 +64,13 @@ public class ShopCartItemController : AuthorizationControllerBase {
/// <param name="requestData"></param>
/// <returns></returns>
[HttpGet("{siteId}/{userId}/{sku}")]
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] string sku, [FromQuery] GetShopCartItemRequestModel requestData) {
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] string sku, [FromQuery] GetShopCartItemLocalizedRequestModel requestData) {
var (cartItem, getCartItemResult) = _shopCartDataProvider.Get(siteId, userId, sku);
if (!getCartItemResult.IsSuccess || cartItem == null)
return getCartItemResult.ToActionResult();
return await AuthorizeAsync(new ShopCartAuthorizationRequirement(CrudActions.Read), cartItem, () => {
return await AuthorizeAsync(User, new ShopCartAuthorizationRequirement(CrudActions.Read), cartItem, () => {
var result = _shopCartItemService.Get(cartItem, requestData);
return result.ToActionResult();
});
@ -92,7 +91,7 @@ public class ShopCartItemController : AuthorizationControllerBase {
if (!getCartItemResult.IsSuccess || cartItem == null)
return getCartItemResult.ToActionResult();
return await AuthorizeAsync(new ShopCartAuthorizationRequirement(CrudActions.Update), cartItem, () => {
return await AuthorizeAsync(User, new ShopCartAuthorizationRequirement(CrudActions.Update), cartItem, () => {
var result = _shopCartItemService.Update(cartItem, requestData);
return result.ToActionResult();
});
@ -112,7 +111,7 @@ public class ShopCartItemController : AuthorizationControllerBase {
if (!getCartItemResult.IsSuccess || cartItem == null)
return getCartItemResult.ToActionResult();
return await AuthorizeAsync(new ShopCartAuthorizationRequirement(CrudActions.Delete), cartItem, () => {
return await AuthorizeAsync(User, new ShopCartAuthorizationRequirement(CrudActions.Delete), cartItem, () => {
var result = _shopCartDataProvider.Delete(cartItem.Id);
return result.ToActionResult();
});

View File

@ -15,7 +15,6 @@ namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ShopCartItemsController : AuthorizationControllerBase {
@ -42,13 +41,13 @@ public class ShopCartItemsController : AuthorizationControllerBase {
/// </summary>
/// <returns></returns>
[HttpGet("{siteId}/{userId}")]
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromQuery] GetShopCartItemsController requestData) {
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromQuery] GetShopCartItemsLocalizedRequestModel requestData) {
var (cartItems, getCartItemsResult) = _shopCartDataProvider.GetAll(siteId, userId);
if (!getCartItemsResult.IsSuccess || cartItems == null)
return getCartItemsResult.ToActionResult();
return await AuthorizeAsync(new ShopCartAuthorizationRequirement(CrudActions.Read), cartItems, () => {
return await AuthorizeAsync(User, new ShopCartAuthorizationRequirement(CrudActions.Read), cartItems, () => {
var result = _shopCartItemsService.Get(cartItems, requestData);
return result.ToActionResult();
});

View File

@ -19,7 +19,6 @@ namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ShopItemController : AuthorizationControllerBase {
@ -41,20 +40,6 @@ public class ShopItemController : AuthorizationControllerBase {
_shopItemService = shopItemService;
}
#region Authless methods
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <returns></returns>
[HttpGet("{siteId}")]
public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] string slug) {
var result = _shopItemService.GetSlug(siteId, slug);
return result.ToActionResult();
}
#endregion
/// <summary>
/// Can Admin, Shop manager
/// </summary>
@ -71,7 +56,7 @@ public class ShopItemController : AuthorizationControllerBase {
var shopItem = requestData.ToDomainObject(sku, userId.Value, siteId);
return await AuthorizeAsync(new ShopAuthorizationRequirement(CrudActions.Create, new List<ShopRole> {
return await AuthorizeAsync(User, new ShopAuthorizationRequirement(CrudActions.Create, new List<ShopRole> {
new ShopRole(Roles.Admin),
new ShopRole(Roles.ShopManager)
}), shopItem, () => {
@ -94,7 +79,7 @@ public class ShopItemController : AuthorizationControllerBase {
if (!getShopItemResult.IsSuccess || shopItem == null)
return getShopItemResult.ToActionResult();
return await AuthorizeAsync(new ShopAuthorizationRequirement(CrudActions.Read, new List<ShopRole> {
return await AuthorizeAsync(User, new ShopAuthorizationRequirement(CrudActions.Read, new List<ShopRole> {
new ShopRole(Roles.Admin),
new ShopRole(Roles.ShopManager)
}), shopItem, () => {
@ -103,6 +88,18 @@ public class ShopItemController : AuthorizationControllerBase {
});
}
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <returns></returns>
[HttpGet("{siteId}")]
public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] string slug) {
var result = _shopItemService.GetSlug(siteId, slug);
return result.ToActionResult();
}
/// <summary>
/// Can Admin, Shop manager
/// </summary>
@ -117,7 +114,7 @@ public class ShopItemController : AuthorizationControllerBase {
if (!getShopItemResult.IsSuccess || shopItem == null)
return getShopItemResult.ToActionResult();
return await AuthorizeAsync(new ShopAuthorizationRequirement(CrudActions.Update, new List<ShopRole> {
return await AuthorizeAsync(User, new ShopAuthorizationRequirement(CrudActions.Update, new List<ShopRole> {
new ShopRole(Roles.Admin),
new ShopRole(Roles.ShopManager)
}), shopItem, () => {
@ -139,7 +136,7 @@ public class ShopItemController : AuthorizationControllerBase {
if (!getShopItemResult.IsSuccess || shopItem == null)
return getShopItemResult.ToActionResult();
return await AuthorizeAsync(new ShopAuthorizationRequirement(CrudActions.Delete, new List<ShopRole> {
return await AuthorizeAsync(User, new ShopAuthorizationRequirement(CrudActions.Delete, new List<ShopRole> {
new ShopRole(Roles.Admin),
new ShopRole(Roles.ShopManager)
}), shopItem, () => {

View File

@ -6,17 +6,16 @@ using DomainResults.Mvc;
using WeatherForecast.Services;
using DataProviders.Collections;
using WeatherForecast.Models.Shop.Requests;
using WeatherForecast.Controllers.Abstractions;
namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ShopItemsController : ControllerBase {
public class ShopItemsController : AuthorizationControllerBase {
private readonly IAuthorizationService _authorizationService;
private readonly IShopCatalogDataProvider _shopCatalogDataProvider;
private readonly IShopItemsService _shopItemsService;
@ -30,8 +29,7 @@ public class ShopItemsController : ControllerBase {
IAuthorizationService authorizationService,
IShopCatalogDataProvider shopCatalogDataProvider,
IShopItemsService shopCatalogService
) {
_authorizationService = authorizationService;
) : base (authorizationService) {
_shopCatalogDataProvider = shopCatalogDataProvider;
_shopItemsService = shopCatalogService;
}
@ -44,7 +42,7 @@ public class ShopItemsController : ControllerBase {
/// <param name="requestData"></param>
/// <returns></returns>
[HttpGet("{siteId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetShopItemsRequestModel requestData) {
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetShopItemsLocalizedRequestModel requestData) {
var result = _shopItemsService.Get(siteId, requestData);
return result.ToActionResult();
}

View File

@ -19,7 +19,6 @@ namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[AllowAnonymous]
[Route("api/[controller]")]
public class TemplateController : AuthorizationControllerBase {
@ -59,7 +58,7 @@ public class TemplateController : AuthorizationControllerBase {
var newFile = new BucketFile(siteId, formFile.FileName, ms.ToArray(), formFile.ContentType);
return await AuthorizeAsync(new TemplateAuthorisationRequirement(CrudActions.Create, new List<TemplateRole> {
return await AuthorizeAsync(User, new TemplateAuthorisationRequirement(CrudActions.Create, new List<TemplateRole> {
new TemplateRole(Roles.Admin)
}), newFile, () => {
var result = _templateService.Post(newFile);
@ -80,7 +79,7 @@ public class TemplateController : AuthorizationControllerBase {
if (!result.IsSuccess || file == null)
return result.ToActionResult();
return await AuthorizeAsync(new TemplateAuthorisationRequirement(CrudActions.Read, new List<TemplateRole> {
return await AuthorizeAsync(User, new TemplateAuthorisationRequirement(CrudActions.Read, new List<TemplateRole> {
new TemplateRole(Roles.Admin)
}), file, () => {
var stream = new MemoryStream(file.Bytes);

View File

@ -3,8 +3,10 @@
using CryptoProvider;
using DomainResults.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WeatherForecast.Controllers.Abstractions;
using WeatherForecast.Models.Initialization.Requests;
using WeatherForecast.Models.Utils.Requests;
using WeatherForecast.Services;
@ -16,8 +18,15 @@ namespace WeatherForecast.Controllers;
///
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class UtilsController : ControllerBase {
public class UtilsController : AuthorizationControllerBase {
/// <summary>
///
/// </summary>
/// <param name="authorizationService"></param>
public UtilsController(
IAuthorizationService authorizationService
) : base(authorizationService) { }
/// <summary>
///

View File

@ -1,5 +1,7 @@
using DomainObjects.Documents.Users;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WeatherForecast.Controllers.Abstractions;
using WeatherForecast.Models.WeatherForecast.Responses;
namespace WeatherForecast.Controllers;
@ -7,9 +9,8 @@ namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase {
[Route("api/[controller]")]
public class WeatherForecastController : AuthorizationControllerBase {
private static readonly string[] Summaries = new[] {
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
@ -17,7 +18,9 @@ public class WeatherForecastController : ControllerBase {
/// <summary>
///
/// </summary>
public WeatherForecastController() { }
public WeatherForecastController(
IAuthorizationService authorizationService
) : base (authorizationService) { }
#region Authless methods

View File

@ -42,6 +42,13 @@ namespace WeatherForecast.Models.Blog.Requests {
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (CurrentPage < 1)
yield return new ValidationResult($"{Errors.WrongOrNotManaged} {nameof(CurrentPage)}");
if (ItemsPerPage < 1)
yield return new ValidationResult($"{Errors.WrongOrNotManaged} {nameof(ItemsPerPage)}");
if (Locale == Locales.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse} {nameof(Locale)}");
}

View File

@ -183,7 +183,7 @@ namespace WeatherForecast.Models.Blog.Requests {
Locale = y.Locale,
Alt = y.Alt,
Target = y.Target,
Titile = y.Title,
Title = y.Title,
Description = y.Description
}).ToList()
}).ToList(),

View File

@ -183,7 +183,7 @@ namespace WeatherForecast.Models.Blog.Requests {
Locale = y.Locale,
Alt = y.Alt,
Target = y.Target,
Titile = y.Title,
Title = y.Title,
Description = y.Description
}).ToList()
}).ToList(),

View File

@ -132,7 +132,7 @@ namespace WeatherForecast.Models.Blog.Responses {
/// <summary>
///
/// </summary>
public class GetBlogItemSlugResponseModel : ResponseModelBase {
public class GetBlogItemLocalizedResponseModel : ResponseModelBase {
/// <summary>
///
@ -221,7 +221,7 @@ namespace WeatherForecast.Models.Blog.Responses {
/// <param name="categories"></param>
/// <param name="author"></param>
/// <param name="locale"></param>
public GetBlogItemSlugResponseModel(BlogDocument blogItem, List<Category> categories, User author, Locales locale) {
public GetBlogItemLocalizedResponseModel(BlogDocument blogItem, List<Category> categories, User author, Locales locale) {
var postItemL10n = blogItem.L10n.Single(x => x.Locale == locale);

View File

@ -19,7 +19,7 @@ namespace WeatherForecast.Models.Blog.Responses {
/// <summary>
///
/// </summary>
public string Locale { get; set; }
public Locales Locale { get; set; }
/// <summary>
///
@ -46,7 +46,7 @@ namespace WeatherForecast.Models.Blog.Responses {
/// </summary>
/// <param name="imageL10n"></param>
public GetBlogItemMediaAttachmentL10nResponseModel(MediaAttachmentL10n imageL10n) {
Locale = imageL10n.Locale.Name;
Locale = imageL10n.Locale;
Alt = imageL10n.Alt;
Target = imageL10n.Target;
Title = imageL10n.Title;

View File

@ -5,7 +5,7 @@ namespace WeatherForecast.Models.Blog.Responses {
/// <summary>
///
/// </summary>
public class GetBlogItemsSlugResponseModel : PaginationModelBase<GetBlogItemSlugResponseModel> {
public class GetBlogItemsLocalizedResponseModel : PaginationModelBase<GetBlogItemLocalizedResponseModel> {
/// <summary>
///
@ -13,7 +13,7 @@ namespace WeatherForecast.Models.Blog.Responses {
/// <param name="currentPage"></param>
/// <param name="totalPages"></param>
/// <param name="items"></param>
public GetBlogItemsSlugResponseModel(int currentPage, int totalPages, List<GetBlogItemSlugResponseModel> items)
public GetBlogItemsLocalizedResponseModel(int currentPage, int totalPages, List<GetBlogItemLocalizedResponseModel> items)
: base(currentPage, totalPages, items) { }
}
}

View File

@ -7,7 +7,7 @@ namespace WeatherForecast.Models.Categories.Requests {
/// <summary>
///
/// </summary>
public class GetCategoryItemSlugRequestModel : RequestModelBase, IValidatableObject {
public class GetCategoryItemLocalizedRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///

View File

@ -0,0 +1,45 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Enumerations;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.Cetegories.Requests {
/// <summary>
///
/// </summary>
public class GetCategoryItemsLocalizedRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public int CurrentPage { get; set; } = 1;
/// <summary>
///
/// </summary>
public int ItemsPerPage { get; set; } = 8;
/// <summary>
///
/// </summary>
public Locales Locale { get; set; } = Locales.Unknown;
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (CurrentPage > 0)
yield return new ValidationResult($"{Errors.WrongOrNotManaged} {nameof(CurrentPage)}");
if (ItemsPerPage > 0)
yield return new ValidationResult($"{Errors.WrongOrNotManaged} {nameof(ItemsPerPage)}");
if (Locale == Locales.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse} {nameof(Locale)}");
}
}
}

View File

@ -1,37 +0,0 @@
using Core.Abstractions.Models;
using DomainObjects.Documents.Categories.L10n;
namespace WeatherForecast.Models.Categories.Responses
{
/// <summary>
///
/// </summary>
public class CategoryL10nModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public string Locale { get; set; }
/// <summary>
///
/// </summary>
public string Slug { get; set; }
/// <summary>
///
/// </summary>
public string Text { get; set; }
/// <summary>
///
/// </summary>
/// <param name="categoryL10n"></param>
public CategoryL10nModel(CategoryL10n categoryL10n) {
Locale = categoryL10n.Locale.Name;
Slug = categoryL10n.Slug;
Text = categoryL10n.Text;
}
}
}

View File

@ -0,0 +1,49 @@
using Core.Abstractions.Models;
using DomainObjects.Documents.Categories;
using DomainObjects.Enumerations;
using WeatherForecast.Models.Categories.Responses;
namespace WeatherForecast.Models.Cetegories.Responses {
/// <summary>
///
/// </summary>
public class GetCategoryItemLocalizedResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public Guid Id { get; set; }
/// <summary>
///
/// </summary>
public Guid SiteId { get; set; }
/// <summary>
///
/// </summary>
public string Slug { get; set; }
/// <summary>
///
/// </summary>
public string Text { get; set; }
/// <summary>
///
/// </summary>
/// <param name="category"></param>
/// <param name="locale"></param>
public GetCategoryItemLocalizedResponseModel(Category category, Locales locale) {
var l10n = category.L10n.Single(x => x.Locale == locale);
Id = category.Id;
SiteId = category.SiteId;
Slug = l10n.Slug;
Text = l10n.Text;
}
}
}

View File

@ -1,6 +1,7 @@
using Core.Abstractions.Models;
using DomainObjects.Enumerations;
using DomainObjects.Documents.Categories.L10n;
using DomainObjects.Documents.Categories;
namespace WeatherForecast.Models.Categories.Responses {
@ -12,7 +13,7 @@ namespace WeatherForecast.Models.Categories.Responses {
/// <summary>
///
/// </summary>
public string Locale { get; set; }
public Locales Locale { get; set; }
/// <summary>
///
@ -29,7 +30,7 @@ namespace WeatherForecast.Models.Categories.Responses {
/// </summary>
/// <param name="categoryL10n"></param>
public GetCategoryItemL10nResponseModel(CategoryL10n categoryL10n) {
Locale = categoryL10n.Locale.Name;
Locale = categoryL10n.Locale;
Slug = categoryL10n.Slug;
Text = categoryL10n.Text;
}
@ -69,7 +70,7 @@ namespace WeatherForecast.Models.Categories.Responses {
///
/// </summary>
/// <param name="category"></param>
public GetCategoryItemResponseModel(DomainObjects.Documents.Categories.Category category) {
public GetCategoryItemResponseModel(Category category) {
Id = category.Id;
SiteId = category.SiteId;
@ -81,7 +82,7 @@ namespace WeatherForecast.Models.Categories.Responses {
/// </summary>
/// <param name="category"></param>
/// <param name="locale"></param>
public GetCategoryItemResponseModel(DomainObjects.Documents.Categories.Category category, Locales locale) {
public GetCategoryItemResponseModel(Category category, Locales locale) {
Id = category.Id;
SiteId = category.SiteId;

View File

@ -0,0 +1,21 @@
using Core.Abstractions.Models;
using Core.Models;
using WeatherForecast.Models.Blog.Responses;
namespace WeatherForecast.Models.Cetegories.Responses {
/// <summary>
///
/// </summary>
public class GetCategoryItemsLocalizedResponseModel : PaginationModelBase<GetCategoryItemLocalizedResponseModel> {
/// <summary>
///
/// </summary>
/// <param name="currentPage"></param>
/// <param name="totalPages"></param>
/// <param name="items"></param>
public GetCategoryItemsLocalizedResponseModel(int currentPage, int totalPages, List<GetCategoryItemLocalizedResponseModel> items)
: base(currentPage, totalPages, items) { }
}
}

View File

@ -0,0 +1,20 @@
using Core.Models;
using WeatherForecast.Models.Categories.Responses;
namespace WeatherForecast.Models.Cetegories.Responses;
/// <summary>
///
/// </summary>
public class GetCategoryItemsResponseModel : PaginationModelBase<GetCategoryItemResponseModel> {
/// <summary>
///
/// </summary>
/// <param name="currentPage"></param>
/// <param name="totalPages"></param>
/// <param name="items"></param>
public GetCategoryItemsResponseModel(int currentPage, int totalPages, List<GetCategoryItemResponseModel> items)
: base(currentPage, totalPages, items) { }
}

View File

@ -1,6 +1,7 @@
using Core.Abstractions.Models;
using DomainObjects;
using DomainObjects.Documents;
using DomainObjects.Enumerations;
using WeatherForecast.Models.Content.Responses.Pages;
namespace WeatherForecast.Models.Content.Responses
@ -19,7 +20,7 @@ namespace WeatherForecast.Models.Content.Responses
/// <summary>
///
/// </summary>
public string? Locale { get; set; }
public Locales? Locale { get; set; }
/// <summary>
///

View File

@ -3,12 +3,12 @@ using Core.Enumerations;
using DomainObjects.Enumerations;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.Categories.Requests {
namespace WeatherForecast.Models.Shop.Requests {
/// <summary>
///
/// </summary>
public class GetCategoryItemsRequestModel : RequestModelBase {
public class GetShopItemLocalizedRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -22,8 +22,7 @@ namespace WeatherForecast.Models.Categories.Requests {
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (Locale == Locales.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse.Name} {(nameof(Locales))}");
yield return new ValidationResult($"{Errors.UnableToParse} {nameof(Locale)}");
}
}
}

View File

@ -8,7 +8,7 @@ namespace WeatherForecast.Models.Shop.Requests {
/// <summary>
///
/// </summary>
public class GetShopItemsRequestModel : RequestModelBase, IValidatableObject {
public class GetShopItemsLocalizedRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
@ -40,6 +40,12 @@ namespace WeatherForecast.Models.Shop.Requests {
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (CurrentPage < 1)
yield return new ValidationResult($"{Errors.WrongOrNotManaged} {nameof(CurrentPage)}");
if (ItemsPerPage < 1)
yield return new ValidationResult($"{Errors.WrongOrNotManaged} {nameof(ItemsPerPage)}");
if (Locale == Locales.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse} {nameof(Locale)}");
}

View File

@ -197,7 +197,7 @@ namespace WeatherForecast.Models.Requests {
Locale = y.Locale,
Alt = y.Alt,
Target = y.Target,
Titile = y.Title,
Title = y.Title,
Description = y.Description
}).ToList()
}).ToList(),

View File

@ -202,7 +202,7 @@ namespace WeatherForecast.Models.Requests {
Locale = y.Locale,
Alt = y.Alt,
Target = y.Target,
Titile = y.Title,
Title = y.Title,
Description = y.Description
}).ToList()
}).ToList(),

View File

@ -0,0 +1,271 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DnsClient;
using DomainObjects;
using DomainObjects.Documents.Categories;
using DomainObjects.Documents.Posts;
using DomainObjects.Documents.Sites;
using DomainObjects.Documents.Users;
using DomainObjects.Enumerations;
namespace WeatherForecast.Models.Shop.Responses {
#region Media attachments
/// <summary>
///
/// </summary>
public class GetShopItemLocalizedMediaAttachmentResponseModel {
/// <summary>
///
/// </summary>
public string Alt { get; set; }
/// <summary>
///
/// </summary>
public string? Target { get; set; }
/// <summary>
///
/// </summary>
public string? Title { get; set; }
/// <summary>
///
/// </summary>
public string? Description { get; set; }
/// <summary>
///
/// </summary>
public string Src { get; set; }
/// <summary>
///
/// </summary>
public MediaTypes MediaType { get; set; }
/// <summary>
///
/// </summary>
/// <param name="mediaAttachment"></param>
/// <param name="locale"></param>
public GetShopItemLocalizedMediaAttachmentResponseModel(MediaAttachment mediaAttachment, Locales locale) {
var l10n = mediaAttachment.L10n.Single(x => x.Locale == locale);
Src = mediaAttachment.Src;
MediaType = mediaAttachment.MediaType;
Alt = l10n.Alt;
Target = l10n.Target;
Title = l10n.Title;
Description = l10n.Description;
}
}
#endregion
#region Author
/// <summary>
///
/// </summary>
public class GetShopItemLocalizedAuthorModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public GetShopItemLocalizedMediaAttachmentResponseModel? Avatar { get; set; }
/// <summary>
///
/// </summary>
public string NickName { get; set; }
/// <summary>
///
/// </summary>
/// <param name="author"></param>
/// <param name="locale"></param>
public GetShopItemLocalizedAuthorModel(User author, Locales locale) {
if (author.Avatar != null)
Avatar = new GetShopItemLocalizedMediaAttachmentResponseModel(author.Avatar, locale);
NickName = author.Username;
}
}
#endregion
#region Category
/// <summary>
///
/// </summary>
public class GetShopItemLocalizedCategoryResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public string Slug { get; set; }
/// <summary>
///
/// </summary>
public string Text { get; set; }
/// <summary>
///
/// </summary>
/// <param name="category"></param>
/// <param name="locale"></param>
public GetShopItemLocalizedCategoryResponseModel(Category category, Locales locale) {
var l10n = category.L10n.Single(x => x.Locale == locale);
Slug = l10n.Slug;
Text = l10n.Text;
}
}
#endregion
/// <summary>
///
/// </summary>
public class GetShopItemLocalizedResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public Guid Id { get; set; }
/// <summary>
///
/// </summary>
public Guid SiteId { get; set; }
/// <summary>
///
/// </summary>
public string Slug { get; set; }
/// <summary>
///
/// </summary>
public string Description { get; set; }
/// <summary>
///
/// </summary>
public string Title { get; set; }
/// <summary>
///
/// </summary>
public string ShortText { get; set; }
/// <summary>
///
/// </summary>
public string? Text { get; set; }
/// <summary>
///
/// </summary>
public string PlainText { get; set; }
/// <summary>
///
/// </summary>
public TextFormat TextFormat { get; set; }
/// <summary>
///
/// </summary>
public List<string>? Badges { get; set; }
/// <summary>
///
/// </summary>
public List<GetShopItemLocalizedCategoryResponseModel> Categories { get; set; }
/// <summary>
///
/// </summary>
public List<GetShopItemLocalizedMediaAttachmentResponseModel>? MediaAttachemnts { get; set; }
/// <summary>
///
/// </summary>
public GetShopItemLocalizedAuthorModel Author { get; set; }
/// <summary>
///
/// </summary>
public string Sku { get; set; }
/// <summary>
///
/// </summary>
public decimal? Rating { get; set; }
/// <summary>
///
/// </summary>
public decimal Price { get; set; }
/// <summary>
///
/// </summary>
public decimal? NewPrice { get; set; }
/// <summary>
///
/// </summary>
public uint? Quantity { get; set; }
/// <summary>
///
/// </summary>
/// <param name="shopItem"></param>
/// <param name="categories"></param>
/// <param name="author"></param>
/// <param name="locale"></param>
public GetShopItemLocalizedResponseModel(ShopDocument shopItem, List<Category> categories, User author, Locales locale) {
var postItemL10n = shopItem.L10n.Single(x => x.Locale == locale);
Id = shopItem.Id;
SiteId = shopItem.SiteId;
Slug = postItemL10n.Slug;
Description = postItemL10n.Description;
Title = postItemL10n.Title;
ShortText = postItemL10n.ShortText;
Text = postItemL10n.Text;
PlainText = postItemL10n.PlainText;
TextFormat = postItemL10n.TextFormat;
Badges = postItemL10n.Badges;
Categories = categories.Select(x => new GetShopItemLocalizedCategoryResponseModel(x, locale)).ToList();
MediaAttachemnts = shopItem.MediaAttachments?.Select(x => new GetShopItemLocalizedMediaAttachmentResponseModel(x, locale)).ToList();
Author = new GetShopItemLocalizedAuthorModel(author, locale);
Sku = shopItem.Sku;
Rating = shopItem.Rating;
Price = shopItem.Price;
NewPrice = shopItem.NewPrice;
Quantity = shopItem.Quantity;
}
}
}

View File

@ -1,11 +1,19 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects;
using DomainObjects.Documents.Categories;
using DomainObjects.Documents.Categories.L10n;
using DomainObjects.Documents.Posts;
using DomainObjects.Documents.Users;
using DomainObjects.Enumerations;
using DomainObjects.L10n;
using WeatherForecast.Models.Blog.Responses;
namespace WeatherForecast.Models.Shop.Responses {
#region Media attachment
/// <summary>
///
/// </summary>
@ -13,7 +21,7 @@ namespace WeatherForecast.Models.Shop.Responses {
/// <summary>
///
/// </summary>
public string Locale { get; set; }
public Locales Locale { get; set; }
/// <summary>
///
@ -40,7 +48,7 @@ namespace WeatherForecast.Models.Shop.Responses {
/// </summary>
/// <param name="imageL10n"></param>
public GetShopItemMediaAttachmentL10nResponseModel(MediaAttachmentL10n imageL10n) {
Locale = imageL10n.Locale.Name;
Locale = imageL10n.Locale;
Alt = imageL10n.Alt;
}
@ -59,37 +67,127 @@ namespace WeatherForecast.Models.Shop.Responses {
/// <summary>
///
/// </summary>
public string? Src { get; set; }
public string Src { get; set; }
/// <summary>
///
/// </summary>
public string? Alt { get; set; }
public MediaTypes MediaType { get; set; }
/// <summary>
///
/// </summary>
/// <param name="image"></param>
public GetShopItemMediaAttachmentResponseModel(MediaAttachment image) {
Src = image.Src;
MediaType = image.MediaType;
L10n = image.L10n.Select(x => new GetShopItemMediaAttachmentL10nResponseModel(x)).ToList();
}
}
#endregion
#region Author
/// <summary>
///
/// </summary>
public class GetShopItemAuthorModel : ResponseModelBase {
/// <summary>
///
/// </summary>
/// <param name="mediaAttachment"></param>
/// <param name="locale"></param>
public GetShopItemMediaAttachmentResponseModel(MediaAttachment mediaAttachment, Locales locale) {
Src = mediaAttachment.Src;
public Guid Id { get; set; }
var l10n = mediaAttachment.L10n.Single(x => x.Locale == locale);
/// <summary>
///
/// </summary>
public GetShopItemMediaAttachmentResponseModel? Avatar { get; set; }
if (l10n != null) {
Alt = l10n.Alt;
}
/// <summary>
///
/// </summary>
public string NickName { get; set; }
/// <summary>
///
/// </summary>
/// <param name="author"></param>
public GetShopItemAuthorModel(User author) {
Id = author.Id;
if (author.Avatar != null)
Avatar = new GetShopItemMediaAttachmentResponseModel(author.Avatar);
NickName = author.Username;
}
}
#endregion
#region Category
/// <summary>
///
/// </summary>
public class GetShopItemCategoryL10nResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public Locales Locale { get; set; }
/// <summary>
///
/// </summary>
public string Slug { get; set; }
/// <summary>
///
/// </summary>
public string Text { get; set; }
/// <summary>
///
/// </summary>
/// <param name="categoryL10n"></param>
public GetShopItemCategoryL10nResponseModel(CategoryL10n categoryL10n) {
Locale = categoryL10n.Locale;
Slug = categoryL10n.Slug;
Text = categoryL10n.Text;
}
}
/// <summary>
///
/// </summary>
public class GetShopItemCategoryResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public Guid Id { get; set; }
/// <summary>
///
/// </summary>
public Guid SiteId { get; set; }
/// <summary>
///
/// </summary>
public List<GetShopItemCategoryL10nResponseModel>? L10n { get; set; }
/// <summary>
///
/// </summary>
/// <param name="category"></param>
public GetShopItemCategoryResponseModel(Category category) {
Id = category.Id;
SiteId = category.SiteId;
L10n = category.L10n.Select(x => new GetShopItemCategoryL10nResponseModel(x)).ToList();
}
}
#endregion
#region Shop item
/// <summary>
///
/// </summary>
@ -98,7 +196,7 @@ namespace WeatherForecast.Models.Shop.Responses {
/// <summary>
///
/// </summary>
public string Locale { get; set; }
public Locales Locale { get; set; }
/// <summary>
///
@ -146,7 +244,7 @@ namespace WeatherForecast.Models.Shop.Responses {
/// </summary>
/// <param name="postItemL10n"></param>
public GetShopItemL10nResponseModel(PostItemL10n postItemL10n) {
Locale = postItemL10n.Locale.Name;
Locale = postItemL10n.Locale;
Slug = postItemL10n.Slug;
Description = postItemL10n.Description;
Title = postItemL10n.Title;
@ -165,6 +263,49 @@ namespace WeatherForecast.Models.Shop.Responses {
/// </summary>
public class GetShopItemResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public Guid Id { get; set; }
/// <summary>
///
/// </summary>
public Guid SiteId { get; set; }
/// <summary>
///
/// </summary>
public List<GetShopItemL10nResponseModel> L10n { get; set; }
/// <summary>
///
/// </summary>
public List<GetShopItemMediaAttachmentResponseModel>? MediaAttachemnts { get; set; }
/// <summary>
///
/// </summary>
public GetShopItemAuthorModel Author { get; set; }
/// <summary>
///
/// </summary>
public DateTime Created { get; set; }
/// <summary>
///
/// </summary>
public List<string>? Tags { get; set; }
/// <summary>
///
/// </summary>
public List<GetShopItemCategoryResponseModel> Categories { get; set; }
/// <summary>
///
/// </summary>
@ -193,28 +334,24 @@ namespace WeatherForecast.Models.Shop.Responses {
/// <summary>
///
/// </summary>
/// <param name="shopCatalogItem"></param>
/// <param name="shopItem"></param>
/// <param name="categories"></param>
public GetShopItemResponseModel(ShopDocument shopCatalogItem, List<DomainObjects.Documents.Categories.Category> categories) {
Sku = shopCatalogItem.Sku;
Rating = shopCatalogItem.Rating;
Price = shopCatalogItem.Price;
NewPrice = shopCatalogItem.NewPrice;
Quantity = shopCatalogItem.Quantity;
}
/// <summary>
///
/// </summary>
/// <param name="shopCatalogItem"></param>
/// <param name="categories"></param>
/// <param name="locale"></param>
public GetShopItemResponseModel(ShopDocument shopCatalogItem, List<DomainObjects.Documents.Categories.Category> categories, Locales locale) {
Sku = shopCatalogItem.Sku;
Rating = shopCatalogItem.Rating;
Price = shopCatalogItem.Price;
NewPrice = shopCatalogItem.NewPrice;
Quantity = shopCatalogItem.Quantity;
/// <param name="author"></param>
public GetShopItemResponseModel(ShopDocument shopItem, List<Category> categories, User author) {
Id = shopItem.Id;
SiteId = shopItem.SiteId;
L10n = shopItem.L10n.Select(x => new GetShopItemL10nResponseModel(x)).ToList();
MediaAttachemnts = shopItem.MediaAttachments?.Select(x => new GetShopItemMediaAttachmentResponseModel(x)).ToList();
Author = new GetShopItemAuthorModel(author);
Created = shopItem.Created;
Tags = shopItem.Tags;
Categories = categories.Select(x => new GetShopItemCategoryResponseModel(x)).ToList();
Sku = shopItem.Sku;
Rating = shopItem.Rating;
Price = shopItem.Price;
NewPrice = shopItem.NewPrice;
Quantity = shopItem.Quantity;
}
}
#endregion
}

View File

@ -0,0 +1,18 @@
using Core.Models;
namespace WeatherForecast.Models.Shop.Responses {
/// <summary>
///
/// </summary>
public class GetShopItemsLocalizedResponseModel : PaginationModelBase<GetShopItemLocalizedResponseModel> {
/// <summary>
///
/// </summary>
/// <param name="currentPage"></param>
/// <param name="totalPages"></param>
/// <param name="items"></param>
public GetShopItemsLocalizedResponseModel(int currentPage, int totalPages, List<GetShopItemLocalizedResponseModel> items)
: base(currentPage, totalPages, items) { }
}
}

View File

@ -9,7 +9,7 @@ namespace WeatherForecast.Models.ShopCart.Requests
/// <summary>
///
/// </summary>
public class GetShopCartItemRequestModel : RequestModelBase, IValidatableObject
public class GetShopCartItemLocalizedRequestModel : RequestModelBase, IValidatableObject
{
/// <summary>

View File

@ -1,32 +0,0 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Enumerations;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.ShopCart.Requests
{
/// <summary>
///
/// </summary>
public class GetShopCartItemsController : RequestModelBase, IValidatableObject
{
/// <summary>
///
/// </summary>
public Locales Locale { get; set; } = Locales.Us;
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Locale == Locales.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse.Name} {nameof(Locales)}");
}
}
}

View File

@ -0,0 +1,45 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Enumerations;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.ShopCart.Requests {
/// <summary>
///
/// </summary>
public class GetShopCartItemsLocalizedRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public int CurrentPage { get; set; } = 1;
/// <summary>
///
/// </summary>
public int ItemsPerPage { get; set; } = 8;
/// <summary>
///
/// </summary>
public Locales Locale { get; set; } = Locales.Us;
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (CurrentPage > 0)
yield return new ValidationResult($"{Errors.WrongOrNotManaged} {nameof(CurrentPage)}");
if (ItemsPerPage > 0)
yield return new ValidationResult($"{Errors.WrongOrNotManaged} {nameof(ItemsPerPage)}");
if (Locale == Locales.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse.Name} {nameof(Locales)}");
}
}
}

View File

@ -11,41 +11,25 @@ namespace WeatherForecast.Models.ShopCart.Requests
/// <summary>
///
/// </summary>
public class PostShopCartItemRequestModel : RequestModelBase, IValidatableObject
public class PostShopCartItemRequestModel : RequestModelBase
{
/// <summary>
///
/// </summary>
public uint? Quantity { get; set; }
public uint Quantity { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public ShopCartDocument ToDomainObject(string sku, Guid userId, Guid siteId)
{
public ShopCartDocument ToDomainObject(string sku, Guid userId, Guid siteId) => new ShopCartDocument() {
Sku = sku,
UserId = userId,
SiteId = siteId,
return new ShopCartDocument()
{
Sku = sku,
UserId = userId,
SiteId = siteId,
Quantity = Quantity.Value,
Created = DateTime.UtcNow
};
}
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Quantity == null || Quantity != null && Quantity == 0)
yield return new ValidationResult($"{nameof(Quantity)} {Errors.NullOrEmpty}");
}
Quantity = Quantity,
Created = DateTime.UtcNow
};
}
}

View File

@ -0,0 +1,149 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects;
using DomainObjects.Documents;
using DomainObjects.Documents.Posts;
using DomainObjects.Enumerations;
using DomainObjects.L10n;
namespace WeatherForecast.Models.ShopCart.Responses {
#region Media attachment
/// <summary>
///
/// </summary>
public class GetShopCartItemLocalizedMediaAttachmentResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public string Src { get; set; }
/// <summary>
///
/// </summary>
public MediaTypes MediaType { get; set; }
/// <summary>
///
/// </summary>
public string? Alt { get; set; }
/// <summary>
///
/// </summary>
public string? Target { get; set; }
/// <summary>
///
/// </summary>
public string? Title { get; set; }
/// <summary>
///
/// </summary>
public string? Description { get; set; }
/// <summary>
///
/// </summary>
/// <param name="mediaAttachment"></param>
/// <param name="locale"></param>
public GetShopCartItemLocalizedMediaAttachmentResponseModel(MediaAttachment mediaAttachment, Locales locale) {
var l10n = mediaAttachment.L10n.Single(x => x.Locale == locale);
Src = mediaAttachment.Src;
MediaType = mediaAttachment.MediaType;
Alt = l10n.Alt;
Target = l10n.Target;
Title = l10n.Title;
Description = l10n.Description;
}
}
#endregion
#region Shop cart item
/// <summary>
///
/// </summary>
public class GetShopCartItemLocalizedResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public string Slug { get; set; }
/// <summary>
///
/// </summary>
public string Sku { get; set; }
/// <summary>
///
/// </summary>
public GetShopCartItemLocalizedMediaAttachmentResponseModel? Image { get; set; }
/// <summary>
///
/// </summary>
public string Title { get; set; }
/// <summary>
///
/// </summary>
public string BrandName { get; set; }
/// <summary>
///
/// </summary>
public string ShortText { get; set; }
/// <summary>
///
/// </summary>
public DateTime Created { get; set; }
/// <summary>
///
/// </summary>
public decimal Price { get; set; }
/// <summary>
///
/// </summary>
public decimal? NewPrice { get; set; }
/// <summary>
///
/// </summary>
public uint? Quantity { get; set; }
/// <summary>
///
/// </summary>
/// <param name="shopItem"></param>
/// <param name="shopCartItem"></param>
/// <param name="locale"></param>
public GetShopCartItemLocalizedResponseModel(ShopDocument shopItem, ShopCartDocument shopCartItem, Locales locale) {
var l10n = shopItem.L10n.Single(x => x.Locale == locale);
Sku = shopItem.Sku;
BrandName = shopItem.BrandName;
Created = shopItem.Created;
Price = shopItem.Price;
NewPrice = shopItem.NewPrice;
Quantity = shopCartItem.Quantity;
Slug = l10n.Slug;
Title = l10n.Title;
ShortText = l10n.ShortText;
var mediaAttachment = shopItem.MediaAttachments?.FirstOrDefault();
if (mediaAttachment != null)
Image = new GetShopCartItemLocalizedMediaAttachmentResponseModel(mediaAttachment, locale);
}
}
#endregion
}

View File

@ -1,4 +1,5 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects;
using DomainObjects.Documents;
using DomainObjects.Documents.Posts;
@ -11,12 +12,12 @@ namespace WeatherForecast.Models.ShopCart.Responses {
/// <summary>
///
/// </summary>
public class GetMediaAttachmentL10nModel : ResponseModelBase {
public class GetShopCartItemMediaAttachmentL10nModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public string Locale { get; set; }
public Locales Locale { get; set; }
/// <summary>
///
@ -42,21 +43,24 @@ namespace WeatherForecast.Models.ShopCart.Responses {
///
/// </summary>
/// <param name="imageL10n"></param>
public GetMediaAttachmentL10nModel(MediaAttachmentL10n imageL10n) {
Locale = imageL10n.Locale.Name;
public GetShopCartItemMediaAttachmentL10nModel(MediaAttachmentL10n imageL10n) {
Locale = imageL10n.Locale;
Alt = imageL10n.Alt;
Target = imageL10n.Target;
Title = imageL10n.Title;
Description = imageL10n.Description;
}
}
/// <summary>
///
/// </summary>
public class GetMediaAttachmentResponseModel : ResponseModelBase {
public class GetShopCartItemMediaAttachmentResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public List<GetMediaAttachmentL10nModel>? L10n { get; set; }
public List<GetShopCartItemMediaAttachmentL10nModel>? L10n { get; set; }
/// <summary>
///
@ -66,52 +70,35 @@ namespace WeatherForecast.Models.ShopCart.Responses {
/// <summary>
///
/// </summary>
public string? Alt { get; set; }
/// <summary>
///
/// </summary>
/// <param name="image"></param>
public GetMediaAttachmentResponseModel(MediaAttachment image) {
L10n = image.L10n.Select(x => new GetMediaAttachmentL10nModel(x)).ToList();
}
public MediaTypes MediaType { get; set; }
/// <summary>
///
/// </summary>
/// <param name="mediaAttachment"></param>
/// <param name="locale"></param>
public GetMediaAttachmentResponseModel(MediaAttachment mediaAttachment, Locales locale) {
public GetShopCartItemMediaAttachmentResponseModel(MediaAttachment mediaAttachment) {
Src = mediaAttachment.Src;
var l10n = mediaAttachment.L10n.Single(x => x.Locale == locale);
if (l10n != null) {
Alt = l10n.Alt;
}
MediaType = mediaAttachment.MediaType;
L10n = mediaAttachment.L10n.Select(x => new GetShopCartItemMediaAttachmentL10nModel(x)).ToList();
}
}
/// <summary>
///
/// </summary>
public class GetShopCartItemResponseModel : ResponseModelBase {
public class GetShopCartItemL10nResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public Locales Locale { get; set; }
/// <summary>
///
/// </summary>
public string Slug { get; set; }
/// <summary>
///
/// </summary>
public string Sku { get; set; }
/// <summary>
///
/// </summary>
public GetMediaAttachmentResponseModel? Image { get; set; }
/// <summary>
///
/// </summary>
@ -120,12 +107,62 @@ namespace WeatherForecast.Models.ShopCart.Responses {
/// <summary>
///
/// </summary>
public string BrandName { get; set; }
public string ShortText { get; set; }
/// <summary>
///
/// </summary>
public string ShortText { get; set; }
/// <param name="postItem"></param>
public GetShopCartItemL10nResponseModel(PostItemL10n postItem) {
Locale = postItem.Locale;
Slug = postItem.Slug;
Title = postItem.Title;
ShortText = postItem.ShortText;
}
}
/// <summary>
///
/// </summary>
public class GetShopCartItemResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public Guid Id { get; set; }
/// <summary>
///
/// </summary>
public Guid SiteId { get; set; }
/// <summary>
///
/// </summary>
public string Sku { get; set; }
/// <summary>
///
/// </summary>
public List<GetShopCartItemL10nResponseModel> L10n { get; set; }
/// <summary>
///
/// </summary>
public GetShopCartItemMediaAttachmentResponseModel? Image { get; set; }
/// <summary>
///
/// </summary>
public string BrandName { get; set; }
/// <summary>
///
@ -152,8 +189,12 @@ namespace WeatherForecast.Models.ShopCart.Responses {
/// </summary>
/// <param name="shopItem"></param>
/// <param name="shopCartItem"></param>
/// <param name="locale"></param>
public GetShopCartItemResponseModel(ShopDocument shopItem, ShopCartDocument shopCartItem, Locales locale) {
public GetShopCartItemResponseModel(ShopDocument shopItem, ShopCartDocument shopCartItem) {
Id = shopCartItem.Id;
SiteId = shopCartItem.SiteId;
L10n = shopItem.L10n.Select(x => new GetShopCartItemL10nResponseModel(x)).ToList();
Sku = shopItem.Sku;
BrandName = shopItem.BrandName;
@ -162,16 +203,11 @@ namespace WeatherForecast.Models.ShopCart.Responses {
NewPrice = shopItem.NewPrice;
Quantity = shopCartItem.Quantity;
var l10n = shopItem.L10n.SingleOrDefault(x => x.Locale == locale);
if (l10n != null) {
Slug = l10n.Slug;
Title = l10n.Title;
ShortText = l10n.ShortText;
}
var mediaAttachmet = shopItem.MediaAttachments?.FirstOrDefault();
if (shopItem.MediaAttachments != null)
Image = new GetMediaAttachmentResponseModel(shopItem.MediaAttachments.First(), locale);
if (mediaAttachmet != null)
Image = new GetShopCartItemMediaAttachmentResponseModel(mediaAttachmet);
}
}

View File

@ -0,0 +1,19 @@
using Core.Models;
namespace WeatherForecast.Models.ShopCart.Responses {
/// <summary>
///
/// </summary>
public class GetShopCartItemsLocalizedResponseModel : PaginationModelBase<GetShopCartItemLocalizedResponseModel> {
/// <summary>
///
/// </summary>
/// <param name="currentPage"></param>
/// <param name="totalPages"></param>
/// <param name="items"></param>
public GetShopCartItemsLocalizedResponseModel(int currentPage, int totalPages, List<GetShopCartItemLocalizedResponseModel> items)
: base(currentPage, totalPages, items) { }
}
}

View File

@ -0,0 +1,19 @@
using Core.Models;
namespace WeatherForecast.Models.ShopCart.Responses {
/// <summary>
///
/// </summary>
public class GetShopCartItemsResponseModels : PaginationModelBase<GetShopCartItemsResponseModels> {
/// <summary>
///
/// </summary>
/// <param name="currentPage"></param>
/// <param name="totalPages"></param>
/// <param name="items"></param>
public GetShopCartItemsResponseModels(int currentPage, int totalPages, List<GetShopCartItemsResponseModels> items)
: base(currentPage, totalPages, items) { }
}
}

View File

@ -9,21 +9,22 @@ namespace WeatherForecast.Services.Abstractions {
/// </summary>
public abstract class PostItemServiceBase<T> : ServiceBase<T> {
/// <summary>
///
/// </summary>
protected readonly ICategoryDataProvider _categoryDataProvider;
private protected readonly ICategoryDataProvider _categoryDataProvider;
private protected readonly IUserDataProvider _userDataProvider;
/// <summary>
///
/// </summary>
/// <param name="logger"></param>
/// <param name="categoryDataProvider"></param>
/// <param name="userDataProvider"></param>
public PostItemServiceBase(
ILogger<T> logger,
ICategoryDataProvider categoryDataProvider
ICategoryDataProvider categoryDataProvider,
IUserDataProvider userDataProvider
) : base(logger) {
_categoryDataProvider = categoryDataProvider;
_userDataProvider = userDataProvider;
}
/// <summary>

View File

@ -36,7 +36,7 @@ namespace WeatherForecast.Services
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(GetBlogItemSlugResponseModel?, IDomainResult) Get(Guid siteId, GetBlogItemLocalizedRequestModel requestData);
(GetBlogItemLocalizedResponseModel?, IDomainResult) Get(Guid siteId, GetBlogItemLocalizedRequestModel requestData);
/// <summary>
///
@ -73,7 +73,7 @@ namespace WeatherForecast.Services
IBlogCatalogDataProvider blogCatalogDataProvider,
ICategoryDataProvider categoryDataProvider,
IUserDataProvider userDataProvider
) : base(logger, categoryDataProvider) {
) : base(logger, categoryDataProvider, userDataProvider) {
_blogCatalogDataProvider = blogCatalogDataProvider;
_userDataProvider = userDataProvider;
}
@ -127,19 +127,23 @@ namespace WeatherForecast.Services
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (GetBlogItemSlugResponseModel?, IDomainResult) Get(Guid siteId, GetBlogItemLocalizedRequestModel requestData) {
public (GetBlogItemLocalizedResponseModel?, IDomainResult) Get(Guid siteId, GetBlogItemLocalizedRequestModel requestData) {
var (blog, getBlogItemResult) = _blogCatalogDataProvider.GetBySlug(siteId, requestData.Slug);
if (!getBlogItemResult.IsSuccess || blog == null)
return IDomainResult.Failed<GetBlogItemSlugResponseModel?>();
var (blogItem, getBlogItemResult) = _blogCatalogDataProvider.GetBySlug(siteId, requestData.Slug);
if (!getBlogItemResult.IsSuccess || blogItem == null)
return IDomainResult.Failed<GetBlogItemLocalizedResponseModel?>();
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(blog.SiteId, blog.Categories);
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(blogItem.SiteId, blogItem.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<GetBlogItemSlugResponseModel?>();
return IDomainResult.Failed<GetBlogItemLocalizedResponseModel?>();
var locale = blog.L10n.Single(x => x.Slug == requestData.Slug).Locale;
var (author, getAuthor) = _userDataProvider.Get(blogItem.Author);
if (!getAuthor.IsSuccess || author == null)
return IDomainResult.Failed<GetBlogItemLocalizedResponseModel?>();
return IDomainResult.Success(new GetBlogItemLocalizedResponseModel(blog, categories, locale));
var locale = blogItem.L10n.Single(x => x.Slug == requestData.Slug).Locale;
return IDomainResult.Success(new GetBlogItemLocalizedResponseModel(blogItem, categories, author, locale));
}
/// <summary>

View File

@ -6,6 +6,7 @@ using DataProviders.Collections;
using WeatherForecast.Models.Blog.Requests;
using WeatherForecast.Models.Blog.Responses;
using DomainObjects.Documents.Categories;
namespace WeatherForecast.Services {
@ -20,7 +21,7 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(GetBlogItemsSlugResponseModel?, IDomainResult) Get(Guid siteId, GetBlogItemsLocalizedRequestModel requestData);
(GetBlogItemsLocalizedResponseModel?, IDomainResult) Get(Guid siteId, GetBlogItemsLocalizedRequestModel requestData);
}
/// <summary>
@ -30,6 +31,7 @@ namespace WeatherForecast.Services {
private readonly IBlogCatalogDataProvider _blogCatalogDataProvider;
private readonly ICategoryDataProvider _categoryDataProvider;
private readonly IUserDataProvider _userDataProvider;
/// <summary>
///
@ -37,13 +39,16 @@ namespace WeatherForecast.Services {
/// <param name="logger"></param>
/// <param name="blogCatalogDataProvider"></param>
/// <param name="categoryDataProvider"></param>
/// <param name="userDataProvider"></param>
public BlogItemsService(
ILogger<BlogItemsService> logger,
IBlogCatalogDataProvider blogCatalogDataProvider,
ICategoryDataProvider categoryDataProvider
ICategoryDataProvider categoryDataProvider,
IUserDataProvider userDataProvider
) : base(logger) {
_blogCatalogDataProvider = blogCatalogDataProvider;
_categoryDataProvider = categoryDataProvider;
_userDataProvider = userDataProvider;
}
/// <summary>
@ -52,24 +57,37 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (GetBlogItemsSlugResponseModel?, IDomainResult) Get(Guid siteId, GetBlogItemsLocalizedRequestModel requestData) {
public (GetBlogItemsLocalizedResponseModel?, IDomainResult) Get(Guid siteId, GetBlogItemsLocalizedRequestModel requestData) {
var (items, result) = _blogCatalogDataProvider.GetAll(siteId, requestData.CurrentPage > 0 ? ((requestData.CurrentPage - 1) * requestData.ItemsPerPage) : 0, requestData.ItemsPerPage);
if (!result.IsSuccess || items == null)
var (count, getCountResult) = _blogCatalogDataProvider.Count(siteId);
if (!getCountResult.IsSuccess || count == null)
return (null, getCountResult);
var skip = (requestData.CurrentPage - 1) * requestData.ItemsPerPage;
var take = requestData.ItemsPerPage;
var totalPages = (int)Math.Ceiling((decimal)count / take);
var (blogitems, result) = _blogCatalogDataProvider.GetAll(siteId, skip, take);
if (!result.IsSuccess || blogitems == null)
return (null, result);
var blogItems = new List<GetBlogItemSlugResponseModel>();
foreach (var item in items) {
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories);
var response = new List<GetBlogItemLocalizedResponseModel>();
foreach (var blogItem in blogitems) {
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, blogItem.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<GetBlogItemsSlugResponseModel?>();
_logger.LogWarning($"Blog item has unkonwn categories {string.Join(',', blogItem.Categories)}");
blogItems.Add(new GetBlogItemLocalizedResponseModel(item, categories, requestData.Locale));
var (author, getAuthor) = _userDataProvider.Get(blogItem.Author);
if (!getAuthor.IsSuccess || author == null)
return IDomainResult.Failed<GetBlogItemsLocalizedResponseModel?>();
response.Add(new GetBlogItemLocalizedResponseModel(blogItem, categories ?? new List<Category>(), author, requestData.Locale));
}
return blogItems.Count > 0
? IDomainResult.Success(new GetBlogItemsResponseModel(requestData.CurrentPage, 0, blogItems))
: IDomainResult.NotFound<GetBlogItemsSlugResponseModel?>();
return response.Count > 0
? IDomainResult.Success(new GetBlogItemsLocalizedResponseModel(requestData.CurrentPage, totalPages, response))
: IDomainResult.NotFound<GetBlogItemsLocalizedResponseModel?>();
}
}
}

View File

@ -4,10 +4,10 @@ using DataProviders.Collections;
using Core.Abstractions;
using WeatherForecast.Models.Category.Requests;
using WeatherForecast.Models.Category.Responses;
using WeatherForecast.Models.Categories.Requests;
using WeatherForecast.Models.Categories.Responses;
using DomainObjects.Enumerations;
using WeatherForecast.Models.CategoryItem.Requests;
using DomainObjects.Documents.Categories;
namespace WeatherForecast.Services {

View File

@ -3,12 +3,9 @@
using DataProviders.Collections;
using Core.Abstractions;
using Core.Enumerations;
using WeatherForecast.Models.Category.Responses;
using DomainObjects.Enumerations;
using WeatherForecast.Models.CategoryItem.Requests;
using WeatherForecast.Models.Cetegories.Responses;
using WeatherForecast.Models.Cetegories.Requests;
namespace WeatherForecast.Services {
@ -23,14 +20,7 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(List<GetCategoryItemResponseModel>?, IDomainResult) Get(Guid siteId, GetCategoryItemsRequestModel requestData);
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <returns></returns>
IDomainResult Delete(Guid siteId);
(GetCategoryItemsLocalizedResponseModel?, IDomainResult) Get(Guid siteId, GetCategoryItemsLocalizedRequestModel requestData);
}
/// <summary>
@ -58,33 +48,23 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (List<GetCategoryItemResponseModel>?, IDomainResult) Get(Guid siteId, GetCategoryItemsRequestModel requestData) {
try {
var (items, result) = _categoryDataProvider.GetAll(siteId);
public (GetCategoryItemsLocalizedResponseModel?, IDomainResult) Get(Guid siteId, GetCategoryItemsLocalizedRequestModel requestData) {
var (count, getCountResult) = _categoryDataProvider.Count(siteId);
if (!getCountResult.IsSuccess || count == null)
return (null, getCountResult);
var skip = (requestData.CurrentPage - 1) * requestData.ItemsPerPage;
var take = requestData.ItemsPerPage;
var totalPages = (int)Math.Ceiling((decimal)count / take);
var (items, result) = _categoryDataProvider.GetAll(siteId);
if (!result.IsSuccess || items == null)
return (null, result);
return IDomainResult.Success(items.Select(x => new GetCategoryItemResponseModel(x, requestData.Locale)).ToList());
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed<List<GetCategoryItemResponseModel>?>(ex.Message);
}
}
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <returns></returns>
public IDomainResult Delete(Guid siteId) {
try {
return _categoryDataProvider.DeleteAll(siteId);
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed(ex.Message);
}
return IDomainResult.Success(new GetCategoryItemsLocalizedResponseModel(requestData.CurrentPage, totalPages, items.Select(x =>
new GetCategoryItemLocalizedResponseModel(x, requestData.Locale)).ToList()));
}
}
}

View File

@ -48,17 +48,11 @@ namespace WeatherForecast.Services {
/// <param name="requestData"></param>
/// <returns></returns>
public (GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, GetContentRequestModel requestData) {
try {
var (content, result) = _contentDataProvider.Get(siteId);
if (!result.IsSuccess || content == null)
return (null, result);
var (content, result) = _contentDataProvider.Get(siteId);
if (!result.IsSuccess || content == null)
return (null, result);
return IDomainResult.Success(new GetContentResponseModel(content.Single(x => x.Localization.Locale == requestData.Locale.Name)));
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed<GetContentResponseModel?>(ex.Message);
}
return IDomainResult.Success(new GetContentResponseModel(content.Single(x => x.Localization.Locale == requestData.Locale)));
}
}
}

View File

@ -31,7 +31,7 @@ public interface IShopCartItemService {
/// <param name="cartItem"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(GetShopCartItemResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, GetShopCartItemRequestModel requestData);
(GetShopCartItemLocalizedResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, GetShopCartItemLocalizedRequestModel requestData);
/// <summary>
///
@ -96,7 +96,7 @@ public class ShopCartItemService : ServiceBase<ShopCartItemService>, IShopCartIt
/// <param name="cartItem"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (GetShopCartItemResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, GetShopCartItemRequestModel requestData) {
public (GetShopCartItemLocalizedResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, GetShopCartItemLocalizedRequestModel requestData) {
var (item, result) = _shopCatalogDataProvider.Get(cartItem.SiteId, cartItem.Sku);
if (!result.IsSuccess || item == null) {
@ -104,10 +104,10 @@ public class ShopCartItemService : ServiceBase<ShopCartItemService>, IShopCartIt
if (!delteResult.IsSuccess)
return (null, delteResult);
return IDomainResult.NotFound<GetShopCartItemResponseModel?>();
return IDomainResult.NotFound<GetShopCartItemLocalizedResponseModel?>();
}
else
return IDomainResult.Success(new GetShopCartItemResponseModel(item, cartItem, requestData.Locale));
return IDomainResult.Success(new GetShopCartItemLocalizedResponseModel(item, cartItem, requestData.Locale));
}
/// <summary>

View File

@ -22,7 +22,7 @@ namespace WeatherForecast.Services
/// <param name="cartItems"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(List<GetShopCartItemResponseModel>?, IDomainResult) Get(List<ShopCartDocument> cartItems, GetShopCartItemsController requestData);
(List<GetShopCartItemLocalizedResponseModel>?, IDomainResult) Get(List<ShopCartDocument> cartItems, GetShopCartItemsLocalizedRequestModel requestData);
}
/// <summary>
@ -54,9 +54,9 @@ namespace WeatherForecast.Services
/// <param name="cartItems"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (List<GetShopCartItemResponseModel>?, IDomainResult) Get(List<ShopCartDocument> cartItems, GetShopCartItemsController requestData) {
public (List<GetShopCartItemLocalizedResponseModel>?, IDomainResult) Get(List<ShopCartDocument> cartItems, GetShopCartItemsLocalizedRequestModel requestData) {
var items = new List<GetShopCartItemResponseModel>();
var items = new List<GetShopCartItemLocalizedResponseModel>();
foreach (var cartItem in cartItems) {
var (item, result) = _shopCatalogDataProvider.Get(cartItem.Id, cartItem.Sku);
if (!result.IsSuccess || item == null) {
@ -65,12 +65,12 @@ namespace WeatherForecast.Services
return (null, delteResult);
}
else
items.Add(new GetShopCartItemResponseModel(item, cartItem, requestData.Locale));
items.Add(new GetShopCartItemLocalizedResponseModel(item, cartItem, requestData.Locale));
}
return items.Count > 0
? IDomainResult.Success(items)
: IDomainResult.NotFound<List<GetShopCartItemResponseModel>?>();
: IDomainResult.NotFound<List<GetShopCartItemLocalizedResponseModel>?>();
}
}
}

View File

@ -7,6 +7,7 @@ using WeatherForecast.Services.Abstractions;
using WeatherForecast.Models.Shop.Responses;
using DomainObjects.Enumerations;
using DomainObjects.Documents.Posts;
using WeatherForecast.Models.Blog.Responses;
namespace WeatherForecast.Services
{
@ -36,7 +37,7 @@ namespace WeatherForecast.Services
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <returns></returns>
(GetShopItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug);
(GetShopItemLocalizedResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug);
/// <summary>
///
@ -55,17 +56,20 @@ namespace WeatherForecast.Services
private readonly IShopCatalogDataProvider _shopCatalogDataProvider;
/// <summary>
///
/// </summary>
/// <param name="logger"></param>
/// <param name="shopCatalogDataProvider"></param>
/// <param name="categoryDataProvider"></param>
/// <param name="userDataProvider"></param>
public ShopItemService(
ILogger<ShopItemService> logger,
IShopCatalogDataProvider shopCatalogDataProvider,
ICategoryDataProvider categoryDataProvider
) : base(logger, categoryDataProvider) {
ICategoryDataProvider categoryDataProvider,
IUserDataProvider userDataProvider
) : base(logger, categoryDataProvider, userDataProvider) {
_shopCatalogDataProvider = shopCatalogDataProvider;
}
@ -106,7 +110,11 @@ namespace WeatherForecast.Services
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<GetShopItemResponseModel?>();
return IDomainResult.Success(new GetShopItemResponseModel(shopItem, categories));
var (author, getAuthor) = _userDataProvider.Get(shopItem.Author);
if (!getAuthor.IsSuccess || author == null)
return IDomainResult.Failed<GetShopItemResponseModel?>();
return IDomainResult.Success(new GetShopItemResponseModel(shopItem, categories, author));
}
/// <summary>
@ -115,24 +123,28 @@ namespace WeatherForecast.Services
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <returns></returns>
public (GetShopItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug) {
public (GetShopItemLocalizedResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug) {
try {
var (item, result) = _shopCatalogDataProvider.GetBySlug(siteId, slug);
var (shopItem, result) = _shopCatalogDataProvider.GetBySlug(siteId, slug);
if (!result.IsSuccess || item == null)
if (!result.IsSuccess || shopItem == null)
return (null, result);
var locale = item.L10n.SingleOrDefault(x => x.Slug == slug)?.Locale ?? Locales.Us;
var locale = shopItem.L10n.SingleOrDefault(x => x.Slug == slug)?.Locale ?? Locales.Us;
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories);
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, shopItem.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<GetShopItemResponseModel?>();
return IDomainResult.Failed<GetShopItemLocalizedResponseModel?>();
return IDomainResult.Success(new GetShopItemResponseModel(item, categories, locale));
var (author, getAuthor) = _userDataProvider.Get(shopItem.Author);
if (!getAuthor.IsSuccess || author == null)
return IDomainResult.Failed<GetShopItemLocalizedResponseModel?>();
return IDomainResult.Success(new GetShopItemLocalizedResponseModel(shopItem, categories, author, locale));
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed<GetShopItemResponseModel?>(ex.Message);
return IDomainResult.Failed<GetShopItemLocalizedResponseModel?>(ex.Message);
}
}

View File

@ -3,13 +3,9 @@
using DataProviders.Collections;
using Core.Abstractions;
using Core.Enumerations;
using WeatherForecast.Models;
using WeatherForecast.Models.Shop.Responses;
using DomainObjects.Enumerations;
using WeatherForecast.Models.Shop.Requests;
using WeatherForecast.Models.Shop.Responses;
namespace WeatherForecast.Services {
@ -24,7 +20,7 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(GetShopItemsResponseModel?, IDomainResult) Get(Guid siteId, GetShopItemsRequestModel requestData);
(GetShopItemsLocalizedResponseModel?, IDomainResult) Get(Guid siteId, GetShopItemsLocalizedRequestModel requestData);
/// <summary>
///
@ -41,6 +37,7 @@ namespace WeatherForecast.Services {
private readonly IShopCatalogDataProvider _shopCatalogDataProvider;
private readonly ICategoryDataProvider _categoryDataProvider;
private readonly IUserDataProvider _userDataProvider;
/// <summary>
///
@ -48,13 +45,16 @@ namespace WeatherForecast.Services {
/// <param name="logger"></param>
/// <param name="shopCatalogDataprovider"></param>
/// <param name="categoryDataProvider"></param>
/// <param name="userDataProvider"></param>
public ShopItemsService(
ILogger<ShopItemsService> logger,
IShopCatalogDataProvider shopCatalogDataprovider,
ICategoryDataProvider categoryDataProvider
ICategoryDataProvider categoryDataProvider,
IUserDataProvider userDataProvider
) : base(logger) {
_shopCatalogDataProvider = shopCatalogDataprovider;
_categoryDataProvider = categoryDataProvider;
_userDataProvider = userDataProvider;
}
/// <summary>
@ -63,30 +63,34 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (GetShopItemsResponseModel?, IDomainResult) Get(Guid siteId, GetShopItemsRequestModel requestData) {
public (GetShopItemsLocalizedResponseModel?, IDomainResult) Get(Guid siteId, GetShopItemsLocalizedRequestModel requestData) {
try {
var (items, result) = _shopCatalogDataProvider.GetAll(siteId, requestData.CurrentPage > 0 ? ((requestData.CurrentPage - 1) * requestData.ItemsPerPage) : 0, requestData.ItemsPerPage);
var (items, result) = _shopCatalogDataProvider.GetAll(siteId, (requestData.CurrentPage - 1) * requestData.ItemsPerPage, requestData.ItemsPerPage);
if (!result.IsSuccess || items == null)
return (null, result);
var shopItems = new List<GetShopItemResponseModel>();
var shopItems = new List<GetShopItemLocalizedResponseModel>();
foreach (var item in items) {
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<GetShopItemsResponseModel?>();
return IDomainResult.Failed<GetShopItemsLocalizedResponseModel?>();
shopItems.Add(new GetShopItemResponseModel(item, categories, requestData.Locale));
var (author, getAuthor) = _userDataProvider.Get(item.Author);
if (!getAuthor.IsSuccess || author == null)
return IDomainResult.Failed<GetShopItemsLocalizedResponseModel?>();
shopItems.Add(new GetShopItemLocalizedResponseModel(item, categories, author, requestData.Locale));
}
return shopItems.Count > 0
? IDomainResult.Success(new GetShopItemsResponseModel(requestData.CurrentPage, 0, shopItems))
: IDomainResult.NotFound<GetShopItemsResponseModel?>();
? IDomainResult.Success(new GetShopItemsLocalizedResponseModel(requestData.CurrentPage, 0, shopItems))
: IDomainResult.NotFound<GetShopItemsLocalizedResponseModel?>();
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed<GetShopItemsResponseModel?>(ex.Message);
return IDomainResult.Failed<GetShopItemsLocalizedResponseModel?>(ex.Message);
}
}

View File

@ -13,6 +13,10 @@ using ImageProvider.Extensions;
using Core.Middlewares;
using Microsoft.AspNetCore.Authorization;
using WeatherForecast.Policies;
using static System.Runtime.InteropServices.JavaScript.JSType;
using DomainObjects.Enumerations;
using System.Security.Claims;
using System.Net;
namespace WeatherForecast {
@ -63,13 +67,40 @@ namespace WeatherForecast {
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.SaveToken = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Convert.FromBase64String(appSettings.JwtConfig.Secret)),
ValidateIssuer = false,
ValidateAudience = false
};
options.Events = new JwtBearerEvents {
OnMessageReceived = context => {
return Task.CompletedTask;
},
OnTokenValidated = context => {
var claims = context.Principal.Identity as ClaimsIdentity;
if (!claims.Claims.Any())
context.Fail("This token has no claims.");
return Task.CompletedTask;
},
OnChallenge = context => {
if (context.AuthenticateFailure != null)
throw new Exception("Authenticate failure.");
throw new Exception ("You are unauthorized to access this resource.");
},
OnAuthenticationFailed = context => {
return Task.FromException(context.Exception);
},
OnForbidden = context => {
return Task.CompletedTask;
}
};
});
}
#endregion
@ -146,8 +177,9 @@ namespace WeatherForecast {
Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
Type = SecuritySchemeType.Http, //We set the scheme type to http since we're using bearer authentication
Scheme = "Bearer",
BearerFormat = "JWT",
});
config.AddSecurityRequirement(new OpenApiSecurityRequirement()
@ -158,7 +190,7 @@ namespace WeatherForecast {
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
Id = "Bearer" //The name of the previously defined security scheme.
},
Scheme = "oauth2",
Name = "Bearer",
@ -170,6 +202,9 @@ namespace WeatherForecast {
});
// c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); //This line
config.MapType<Locales>(() => new OpenApiSchema { Type = "string" });
});
#endregion
}

View File

@ -20,16 +20,16 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="DomainResult" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.10" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="Serilog.Enrichers.Span" Version="2.3.0" />
<PackageReference Include="DomainResult" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.4" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
<PackageReference Include="Serilog.Enrichers.Span" Version="3.1.0" />
<PackageReference Include="Serilog.Expressions" Version="3.4.1" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="5.0.1" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<ItemGroup>

View File

@ -22,6 +22,9 @@ services:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:7151;http://+:5133
ports:
- "7151:7151"
- "5133:5133"
volumes:
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro

View File

@ -3,4 +3,4 @@ WiredTiger 10.0.2: (December 21, 2021)
WiredTiger version
major=10,minor=0,patch=2
file:WiredTiger.wt
access_pattern_hint=none,allocation_size=4KB,app_metadata=,assert=(commit_timestamp=none,durable_timestamp=none,read_timestamp=none,write_timestamp=off),block_allocation=best,block_compressor=,cache_resident=false,checksum=on,collator=,columns=,dictionary=0,encryption=(keyid=,name=),format=btree,huffman_key=,huffman_value=,id=0,ignore_in_memory_cache_size=false,internal_item_max=0,internal_key_max=0,internal_key_truncate=true,internal_page_max=4KB,key_format=S,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=0,log=(enabled=true),memory_page_image_max=0,memory_page_max=5MB,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=false,prefix_compression_min=4,readonly=false,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,tiered_object=false,tiered_storage=(auth_token=,bucket=,bucket_prefix=,cache_directory=,local_retention=300,name=,object_target_size=0),value_format=S,verbose=[],version=(major=1,minor=1),write_timestamp_usage=none,checkpoint=(WiredTigerCheckpoint.121117=(addr="018081e42f982df28181e4a30456e28281e43b45267c808080e3022fc0e3010fc0",order=121117,time=1679264073,size=81920,newest_start_durable_ts=0,oldest_start_ts=0,newest_txn=534,newest_stop_durable_ts=0,newest_stop_ts=-1,newest_stop_txn=-11,prepare=0,write_gen=363869,run_write_gen=363077)),checkpoint_backup_info=,checkpoint_lsn=(56,191744)
access_pattern_hint=none,allocation_size=4KB,app_metadata=,assert=(commit_timestamp=none,durable_timestamp=none,read_timestamp=none,write_timestamp=off),block_allocation=best,block_compressor=,cache_resident=false,checksum=on,collator=,columns=,dictionary=0,encryption=(keyid=,name=),format=btree,huffman_key=,huffman_value=,id=0,ignore_in_memory_cache_size=false,internal_item_max=0,internal_key_max=0,internal_key_truncate=true,internal_page_max=4KB,key_format=S,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=0,log=(enabled=true),memory_page_image_max=0,memory_page_max=5MB,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=false,prefix_compression_min=4,readonly=false,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,tiered_object=false,tiered_storage=(auth_token=,bucket=,bucket_prefix=,cache_directory=,local_retention=300,name=,object_target_size=0),value_format=S,verbose=[],version=(major=1,minor=1),write_timestamp_usage=none,checkpoint=(WiredTigerCheckpoint.123211=(addr="018081e4f52354c18181e493d377368281e4a22aa0f5808080e301ffc0e3010fc0",order=123211,time=1679862041,size=81920,newest_start_durable_ts=0,oldest_start_ts=0,newest_txn=154,newest_stop_durable_ts=0,newest_stop_ts=-1,newest_stop_txn=-11,prepare=0,write_gen=370276,run_write_gen=370143)),checkpoint_backup_info=,checkpoint_lsn=(70,62976)

Some files were not shown because too many files have changed in this diff Show More