(refactor): request and response models

This commit is contained in:
Maksym Sadovnychyy 2023-03-14 20:30:38 +01:00
parent 023d3b065c
commit 4c961920af
124 changed files with 3111 additions and 1336 deletions

View File

@ -1,10 +0,0 @@
smtpService.Connect("smtp.ionos.it", 465, true);
smtpService.Authenticate("commercial@maks-it.com", "E23{R#<X&#Lyz");
Company Inc, 3 Abbey Road, San Francisco CA 94102
Don't like these emails? Unsubscribe.
Powered by MAKS-IT.com.

View File

@ -0,0 +1,148 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>{{subject}}</title>
<style>
@media only screen and (max-width: 620px) {
table.body h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table.body p,
table.body ul,
table.body ol,
table.body td,
table.body span,
table.body a {
font-size: 16px !important;
}
table.body .wrapper,
table.body .article {
padding: 10px !important;
}
table.body .content {
padding: 0 !important;
}
table.body .container {
padding: 0 !important;
width: 100% !important;
}
table.body .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table.body .btn table {
width: 100% !important;
}
table.body .btn a {
width: 100% !important;
}
table.body .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important;
}
}
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
#MessageViewBody a {
color: inherit;
text-decoration: none;
font-size: inherit;
font-family: inherit;
font-weight: inherit;
line-height: inherit;
}
.btn-primary table td:hover {
background-color: #34495e !important;
}
.btn-primary a:hover {
background-color: #34495e !important;
border-color: #34495e !important;
}
}
</style>
</head>
<body style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
<span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">This is preheader text. Some clients will show this text as a preview.</span>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f6f6f6; width: 100%;" width="100%" bgcolor="#f6f6f6">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">&nbsp;</td>
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; max-width: 580px; padding: 10px; width: 580px; margin: 0 auto;" width="580" valign="top">
<div class="content" style="box-sizing: border-box; display: block; margin: 0 auto; max-width: 580px; padding: 10px;">
<!-- START CENTERED WHITE CONTAINER -->
<table role="presentation" class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background: #ffffff; border-radius: 3px; width: 100%;" width="100%">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper" style="font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 20px;" valign="top">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;" width="100%">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">Hello, {{userName}}</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">We have recieved your account password recovery request.<br />
In case if it wasn't you, please ignore this email.</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">Your password recovery token: {{passwordRecoveryToken}}</p>
</td>
</tr>
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- END CENTERED WHITE CONTAINER -->
<!-- START FOOTER -->
<div class="footer" style="clear: both; margin-top: 10px; text-align: center; width: 100%;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;" width="100%">
<tr>
<td class="content-block powered-by" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;" valign="top" align="center">
Powered by <a href="{{poweredBy.target}}" style="color: #999999; font-size: 12px; text-align: center; text-decoration: none;">{{poweredBy.anchorText}}</a>.
</td>
</tr>
</table>
</div>
<!-- END FOOTER -->
</div>
</td>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">&nbsp;</td>
</tr>
</table>
</body>
</html>

View File

@ -3,12 +3,12 @@ using System.Diagnostics.CodeAnalysis;
namespace Core.Abstractions.Models {
public abstract class RequestModelBase : ModelBase, IValidatableObject {
public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
public abstract class RequestModelBase : ModelBase {
// public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
}
public abstract class RequestModelBase<T> : ModelBase, IValidatableObject {
public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
}
//public abstract class RequestModelBase<T> : ModelBase, IValidatableObject {
// public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
//}
}

View File

@ -1,9 +1,31 @@
using Core.Abstractions;
using System.Diagnostics.CodeAnalysis;
namespace Core.Enumerations;
public class MediaTypes : Enumeration {
public class MediaTypes : Enumeration, IParsable<MediaTypes> {
public static MediaTypes Unknown = new(-1, "Unknown");
public static MediaTypes Image = new(0, "image");
public static MediaTypes Video = new(1, "video");
public static MediaTypes Document = new(1, "document");
private MediaTypes(int id, string displayName) : base(id, displayName) { }
public static MediaTypes Parse(string s, IFormatProvider? provider) {
if (!TryParse(s, provider, out var result)) {
throw new ArgumentException("Could not parse supplied value.", nameof(s));
}
return result;
}
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out MediaTypes result) {
result = Unknown;
try {
result = FromDisplayName<MediaTypes>(s ?? "");
return true;
}
catch {
return false;
}
}
}

View File

@ -9,7 +9,7 @@ namespace DataProviders.Buckets {
public Guid Id { get; private set; }
public Guid SiteId { get; private set; }
public Guid? UserId { get; private set; }
public Guid? UserId { get; set; }
public DateTime? Published { get; private set; }

View File

@ -7,6 +7,7 @@ using MongoDB.Driver.GridFS;
using DataProviders.Buckets.Abstractions;
using MongoDB.Bson;
using Extensions;
using DomainObjects.Documents.Users;
namespace DataProviders.Buckets {
@ -37,6 +38,7 @@ namespace DataProviders.Buckets {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
(BucketFile?, IDomainResult) Download(Guid siteId, Guid fileId);
@ -48,10 +50,17 @@ namespace DataProviders.Buckets {
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
(BucketFile?, IDomainResult) Download(Guid siteId, Guid userId, Guid fileId);
(BucketFile?, IDomainResult) Download(Guid siteId, Guid? userId, Guid fileId);
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileIds"></param>
/// <returns></returns>
(List<BucketFile>?, IDomainResult) DownloadMany(Guid siteId, Guid? userId, List<Guid> fileIds);
(List<BucketFile>?, IDomainResult) DownloadMany(Guid siteId, Guid userId, List<Guid> fileIds);
/// <summary>
///
@ -60,7 +69,7 @@ namespace DataProviders.Buckets {
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
IDomainResult DeleteOne(Guid siteId, Guid userId, Guid fileId);
IDomainResult DeleteOne(Guid siteId, Guid? userId, Guid fileId);
/// <summary>
///
@ -68,11 +77,11 @@ namespace DataProviders.Buckets {
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <returns></returns>
IDomainResult DeleteMany(Guid siteId, Guid userId);
IDomainResult DeleteAll(Guid siteId, Guid? userId);
}
/// <summary>
///
/// https://stackoverflow.com/questions/32227284/mongo-c-sharp-driver-building-filter-dynamically-with-nesting
/// </summary>
public class ImageBucketDataProvider : BucketDataProviderBase, IImageBucketDataProvider {
@ -119,26 +128,8 @@ namespace DataProviders.Buckets {
#endregion
#region Download
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
public (BucketFile?, IDomainResult) Download(Guid siteId, Guid fileId) {
var filter = Builders<GridFSFileInfo>.Filter.And(
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
Builders<GridFSFileInfo>.Filter.Not(Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["published"], "")),
Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, $"{fileId}")
);
var (list, result) = Download(filter);
if (!result.IsSuccess || list == null)
return (null, result);
return (list.First(), result);
}
public (BucketFile?, IDomainResult) Download(Guid siteId, Guid fileId) =>
Download(siteId, null, fileId);
/// <summary>
///
@ -147,14 +138,16 @@ namespace DataProviders.Buckets {
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
public (BucketFile?, IDomainResult) Download(Guid siteId, Guid userId, Guid fileId) {
public (BucketFile?, IDomainResult) Download(Guid siteId, Guid? userId, Guid fileId) {
var filter = Builders<GridFSFileInfo>.Filter.And(
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}"),
Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, $"{fileId}")
);
if (userId != null)
filter &= Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}");
var (list, result) = Download(filter);
if (!result.IsSuccess || list == null)
@ -170,9 +163,8 @@ namespace DataProviders.Buckets {
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
public (List<BucketFile>?, IDomainResult) DownloadMany(Guid siteId, Guid userId, List<Guid> fileIds) {
public (List<BucketFile>?, IDomainResult) DownloadMany(Guid siteId, Guid? userId, List<Guid> fileIds) {
var builder = Builders<GridFSFileInfo>.Filter;
@ -238,24 +230,34 @@ namespace DataProviders.Buckets {
#endregion
#region Delete
public IDomainResult DeleteOne(Guid siteId, Guid userId, Guid fileId) =>
public IDomainResult DeleteOne(Guid siteId, Guid? userId, Guid fileId) =>
DeleteOneAsync(siteId, userId, fileId).Result;
public Task<IDomainResult> DeleteOneAsync(Guid siteId, Guid userId, Guid fileId) =>
DeleteAsync(Builders<GridFSFileInfo>.Filter.And(
public Task<IDomainResult> DeleteOneAsync(Guid siteId, Guid? userId, Guid fileId) {
var filter = Builders<GridFSFileInfo>.Filter.And(
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}"),
Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, $"{fileId}")
));
);
public IDomainResult DeleteMany(Guid siteId, Guid userId) =>
DeleteManyAsync(siteId, userId).Result;
if (userId != null)
filter &= Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}");
public Task<IDomainResult> DeleteManyAsync(Guid siteId, Guid userId) =>
DeleteAsync(Builders<GridFSFileInfo>.Filter.And(
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}")
));
return DeleteAsync(filter);
}
public IDomainResult DeleteAll(Guid siteId, Guid? userId) =>
DeleteAllAsync(siteId, userId).Result;
public Task<IDomainResult> DeleteAllAsync(Guid siteId, Guid? userId) {
var filter = Builders<GridFSFileInfo>.Filter.And(
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}")
);
if (userId != null)
filter &= Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}");
return DeleteAsync(filter);
}
#endregion
}
}

View File

@ -2,13 +2,17 @@
namespace DomainObjects.Documents.Users;
public class Roles : Enumeration
{
public class Roles : Enumeration {
/// <summary>
/// The most powerful user role because it gives you access to everything. As the website owner, this should be your role
/// </summary>
public static readonly Roles Admin = new(0, "Admin");
/// <summary>
///
/// </summary>
public static readonly Roles Everyone = new(-1, "Everyone");
/// <summary>
/// The most powerful user role because it gives you access to everything. As the website owner, this should be your role
/// </summary>
public static readonly Roles Admin = new(0, "Admin");
/// <summary>
/// This user is typically responsible for managing content. Editors can add, edit, publish, and delete any posts and media, including those written by other users. Editors can also moderate, edit, and delete comments, and add and edit categories and tags
@ -41,5 +45,4 @@ public class Roles : Enumeration
public static readonly Roles ShopManager = new(6, "Shop manager");
private Roles(int id, string displayName) : base(id, displayName) { }
}

View File

@ -1,10 +1,32 @@
using Core.Abstractions;
using System.Diagnostics.CodeAnalysis;
namespace DomainObjects.Enumerations;
public class Locales : Enumeration {
public class Locales : Enumeration, IParsable<Locales> {
public static Locales Unknown = new(-1, "Unknown");
public static Locales Us = new(0, "en-US");
public static Locales Ru = new(1, "ru-RU");
public static Locales It = new(2, "it-IT");
private Locales(int id, string displayName) : base (id, displayName) { }
public static Locales Parse(string s, IFormatProvider? provider) {
if (!TryParse(s, provider, out var result)) {
throw new ArgumentException("Could not parse supplied value.", nameof(s));
}
return result;
}
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out Locales result) {
result = Unknown;
try {
result = FromDisplayName<Locales>(s ?? "");
return true;
}
catch {
return false;
}
}
}

View File

@ -1,10 +1,32 @@
using Core.Abstractions;
using System.Diagnostics.CodeAnalysis;
namespace DomainObjects.Enumerations;
public class TextFormat : Enumeration {
public class TextFormat : Enumeration, IParsable<TextFormat> {
public static readonly TextFormat Unknown = new(-1, "Unknown");
public static readonly TextFormat Html = new(0, "HTML");
public static readonly TextFormat Md = new(1, "MD");
private TextFormat(int id, string displayName) : base(id, displayName) { }
public static TextFormat Parse(string s, IFormatProvider? provider) {
if (!TryParse(s, provider, out var result)) {
throw new ArgumentException("Could not parse supplied value.", nameof(s));
}
return result;
}
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out TextFormat result) {
result = Unknown;
try {
result = FromDisplayName<TextFormat>(s ?? "");
return true;
}
catch {
return false;
}
}
}

View File

@ -42,7 +42,7 @@ public class AccountController : ControllerBase {
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPost("[action]")]
public IActionResult Authenticate([FromBody] AuthenticationRequestModel requestData) {
public IActionResult Authenticate([FromBody] PostAuthenticationRequestModel requestData) {
var result = _accountService.Authenticate(requestData);
return result.ToActionResult();
}
@ -53,7 +53,17 @@ public class AccountController : ControllerBase {
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPost("[action]")]
public IActionResult Register([FromBody] RegisterRequestModel requestData) {
public IActionResult Register([FromBody] PostAccountCreateRequestModel requestData) {
return BadRequest();
}
/// <summary>
///
/// </summary>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPut("[action]/{userId}")]
public IActionResult Confirm([FromBody] PutAccountConfirmRequestModel requestData) {
return BadRequest();
}
@ -65,7 +75,7 @@ public class AccountController : ControllerBase {
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
[HttpPut($"{_password}/[action]")]
public IActionResult Recovery([FromBody] PasswordRecoveryRequestModel requestData) {
public IActionResult Recovery([FromBody] PutPasswordRecoveryRequestModel requestData) {
var hostName = Request?.Headers["X-Forwarded-Host"].FirstOrDefault();
if (hostName == null)
@ -83,7 +93,7 @@ public class AccountController : ControllerBase {
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
[HttpPut($"{_password}/[action]")]
public IActionResult Reset([FromBody] PasswordResetRequestModel requestData) {
public IActionResult Reset([FromBody] PutPasswordResetRequestModel requestData) {
var result = _accountService.PasswordReset(requestData);
return result.ToActionResult();
}
@ -96,7 +106,7 @@ public class AccountController : ControllerBase {
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPut($"{_password}/[action]/{{userId}}")]
public async Task<IActionResult> Change([FromRoute] Guid userId, [FromBody] PasswordChangeRequestModel requestData) {
public async Task<IActionResult> Change([FromRoute] Guid userId, [FromBody] PutPasswordChangeRequestModel requestData) {
var (user, getUserResult) = _userDataProvider.Get(userId);
if (!getUserResult.IsSuccess || user == null)

View File

@ -11,6 +11,8 @@ using DataProviders.Collections;
using Extensions;
using DomainResults.Common;
using DomainObjects.Documents.Posts;
using WeatherForecast.Models.BlogItem.Requests;
using DomainObjects.Documents.Users;
namespace WeatherForecast.Controllers;
@ -46,24 +48,24 @@ public class BlogItemController : ControllerBase {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpGet("{siteId}")]
public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] string slug) {
var result = _blogItemService.GetSlug(siteId, slug);
public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] GetBlogItemSlugRequestModel requestData) {
var result = _blogItemService.GetSlug(siteId, requestData);
return result.ToActionResult();
}
#endregion
/// <summary>
///
/// Can only Admin, Editor, Author, Contributor (cannot set publish date)
/// </summary>
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPost("{siteId}")]
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromBody] BlogItemRequestModel requestData) {
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromBody] PostBlogItemRequestModel requestData) {
var userId = User?.Identity?.Name?.ToNullableGuid();
if (userId == null)
@ -72,7 +74,14 @@ public class BlogItemController : ControllerBase {
var blogItem = requestData.ToDomainObject(userId.Value, siteId);
if ((await _authorizationService.AuthorizeAsync(User, new List<BlogDocument> { blogItem }, new BlogAuthorizationRequirement {
Action = CrudActions.Create
Action = CrudActions.Create,
Roles = new List<BlogRole> {
new BlogRole { Role = Roles.Admin },
new BlogRole { Role = Roles.Editor },
new BlogRole { Role = Roles.Author, OwnOnly = true },
new BlogRole { Role = Roles.Contributor, OwnOnly = true },
new BlogRole { Role = Roles.ShopManager }
}
})).Succeeded) {
var result = _blogItemService.Post(blogItem);
return result.ToActionResult();
@ -83,6 +92,7 @@ public class BlogItemController : ControllerBase {
/// <summary>
/// Returns full object
/// Can only Admin, Editor, Author, Contributor
/// </summary>
/// <returns></returns>
[HttpGet("{siteId}/{blogId}")]
@ -93,7 +103,14 @@ public class BlogItemController : ControllerBase {
return getBlogItemResult.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<BlogDocument> { blogItem }, new BlogAuthorizationRequirement {
Action = CrudActions.Read
Action = CrudActions.Read,
Roles = new List<BlogRole> {
new BlogRole { Role = Roles.Admin },
new BlogRole { Role = Roles.Editor },
new BlogRole { Role = Roles.Author, OwnOnly = true },
new BlogRole { Role = Roles.Contributor, OwnOnly = true },
new BlogRole { Role = Roles.ShopManager }
}
})).Succeeded) {
var result = _blogItemService.Get(blogItem);
return result.ToActionResult();
@ -103,21 +120,28 @@ public class BlogItemController : ControllerBase {
}
/// <summary>
///
/// Can only Admin, Editor, Author (own), Contributor (own, not yet pubblished)
/// </summary>
/// <param name="siteId"></param>
/// <param name="blogId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPut("{siteId}/{blogId}")]
public async Task<IActionResult> Update([FromRoute] Guid siteId, [FromRoute] Guid blogId, [FromBody] BlogItemRequestModel requestData) {
public async Task<IActionResult> Update([FromRoute] Guid siteId, [FromRoute] Guid blogId, [FromBody] PutBlogItemRequestModel requestData) {
var (blogItem, getBlogItemResult) = _blogCatalogDataProvider.Get(siteId, blogId);
if (!getBlogItemResult.IsSuccess || blogItem == null)
return getBlogItemResult.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<BlogDocument> { blogItem }, new BlogAuthorizationRequirement {
Action = CrudActions.Update
Action = CrudActions.Update,
Roles = new List<BlogRole> {
new BlogRole { Role = Roles.Admin },
new BlogRole { Role = Roles.Editor },
new BlogRole { Role = Roles.Author, OwnOnly = true },
new BlogRole { Role = Roles.Contributor, OwnOnly = true, DenyPublished = true },
new BlogRole { Role = Roles.ShopManager }
}
})).Succeeded) {
var result = _blogItemService.Update(blogItem, requestData);
return result.ToActionResult();
@ -127,7 +151,7 @@ public class BlogItemController : ControllerBase {
}
/// <summary>
///
/// Can only Admin, Editor, Author (own), Contributor (own, not yet pubblished)
/// </summary>
/// <param name="siteId"></param>
/// <param name="blogId"></param>
@ -140,7 +164,14 @@ public class BlogItemController : ControllerBase {
return getBlogItemResult.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<BlogDocument> { blogItem }, new BlogAuthorizationRequirement {
Action = CrudActions.Delete
Action = CrudActions.Delete,
Roles = new List<BlogRole> {
new BlogRole { Role = Roles.Admin },
new BlogRole { Role = Roles.Editor },
new BlogRole { Role = Roles.Author, OwnOnly = true },
new BlogRole { Role = Roles.Contributor, OwnOnly = true, DenyPublished = true },
new BlogRole { Role = Roles.ShopManager }
}
})).Succeeded) {
var result = _blogCatalogDataProvider.Delete(blogItem.Id);
return result.ToActionResult();

View File

@ -8,6 +8,7 @@ using WeatherForecast.Policies;
using Core.Enumerations;
using DataProviders.Collections;
using WeatherForecast.Models.Requests;
using WeatherForecast.Models.BlogItem.Requests;
namespace WeatherForecast.Controllers;
@ -43,35 +44,12 @@ public class BlogItemsController : ControllerBase {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="category"></param>
/// <param name="searchText"></param>
/// <param name="currentPage"></param>
/// <param name="itemsPerPage"></param>
/// <param name="locale"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpGet("{siteId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] Guid? category, [FromQuery] string? searchText, [FromQuery] int? currentPage, [FromQuery] int? itemsPerPage, [FromQuery] string? locale) {
var result = _blogItemsService.Get(siteId, category, currentPage ?? 1, itemsPerPage ?? 8, locale, searchText);
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetBlogItemsRequestModel requestData) {
var result = _blogItemsService.Get(siteId, requestData);
return result.ToActionResult();
}
#endregion
//[HttpDelete("{siteId}")]
//public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromBody] BlogItemsRequestModel requestData) {
// var (blogItems, getBlogItemsResult) = _blogCatalogDataProvider.GetMany(siteId, requestData.Ids);
// if (!getBlogItemsResult.IsSuccess || blogItems == null)
// return getBlogItemsResult.ToActionResult();
// if ((await _authorizationService.AuthorizeAsync(User, blogItems, new BlogAuthorizationRequirement {
// WhiteListToken = true,
// SameAuthor = true,
// Action = CrudActions.Delete
// })).Succeeded) {
// var result = _blogCatalogDataProvider.DeleteMany(siteId, requestData.Ids);
// return result.ToActionResult();
// }
// return Unauthorized();
//}
}

View File

@ -7,6 +7,8 @@ using WeatherForecast.Services;
using WeatherForecast.Policies;
using Core.Enumerations;
using WeatherForecast.Models.Category.Requests;
using WeatherForecast.Models.CategoryItem.Requests;
using DomainObjects.Documents.Users;
namespace WeatherForecast.Controllers;
@ -38,24 +40,29 @@ public class CategoryItemController : ControllerBase {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <param name="requestData"></param>
[HttpGet("{siteId}")]
public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] string slug) {
var result = _categoryItemService.GetSlug(siteId, slug);
public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] GetCategoryItemSlugRequestModel requestData) {
var result = _categoryItemService.GetSlug(siteId, requestData);
return result.ToActionResult();
}
#endregion
/// <summary>
///
/// Can Admin, Editor, Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPost("{siteId}")]
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromBody] CategoryItemRequestModel requestData) {
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromBody] PostCategoryItemRequestModel requestData) {
if ((await _authorizationService.AuthorizeAsync(User, null, new CategoryAuthorizationRequirement {
Action = CrudActions.Create
Action = CrudActions.Create,
Roles = new List<CategoryRole> {
new CategoryRole { Role = Roles.Admin },
new CategoryRole { Role = Roles.Editor },
new CategoryRole { Role = Roles.ShopManager }
}
})).Succeeded) {
var result = _categoryItemService.Post(siteId, requestData);
return result.ToActionResult();
@ -67,6 +74,7 @@ public class CategoryItemController : ControllerBase {
/// <summary>
/// Returns full object
/// Can Admin, Editor, Author, Contributor, Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="categoryId"></param>
@ -74,27 +82,39 @@ public class CategoryItemController : ControllerBase {
[HttpGet("{siteId}/{categoryId}")]
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid categoryId) {
if ((await _authorizationService.AuthorizeAsync(User, null, new CategoryAuthorizationRequirement {
Action = CrudActions.Read
})).Succeeded) {
Action = CrudActions.Read,
Roles = new List<CategoryRole> {
new CategoryRole { Role = Roles.Admin },
new CategoryRole { Role = Roles.Editor },
new CategoryRole { Role = Roles.Author },
new CategoryRole { Role = Roles.Contributor },
new CategoryRole { Role = Roles.ShopManager },
}
})).Succeeded) {
var result = _categoryItemService.Get(siteId, categoryId);
return result.ToActionResult();
}
}
else {
return Unauthorized();
}
}
/// <summary>
///
/// Can Admin, Editor, Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="categoryId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPut("{siteId}/{categoryId}")]
public async Task<IActionResult> Update([FromRoute] Guid siteId, [FromRoute] Guid categoryId, [FromBody] CategoryItemRequestModel requestData) {
public async Task<IActionResult> Update([FromRoute] Guid siteId, [FromRoute] Guid categoryId, [FromBody] PutCategoryItemRequestModel requestData) {
if ((await _authorizationService.AuthorizeAsync(User, null, new CategoryAuthorizationRequirement {
Action = CrudActions.Update
Action = CrudActions.Update,
Roles = new List<CategoryRole> {
new CategoryRole { Role = Roles.Admin },
new CategoryRole { Role = Roles.Editor },
new CategoryRole { Role = Roles.ShopManager }
}
})).Succeeded) {
var result = _categoryItemService.Update(siteId, categoryId, requestData);
return result.ToActionResult();
@ -104,7 +124,7 @@ public class CategoryItemController : ControllerBase {
}
/// <summary>
///
/// Can Admin only
/// </summary>
/// <param name="siteId"></param>
/// <param name="categoryId"></param>
@ -112,7 +132,10 @@ public class CategoryItemController : ControllerBase {
[HttpDelete("{siteId}/{categoryId}")]
public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid categoryId) {
if ((await _authorizationService.AuthorizeAsync(User, null, new CategoryAuthorizationRequirement {
Action = CrudActions.Delete
Action = CrudActions.Delete,
Roles = new List<CategoryRole> {
new CategoryRole { Role = Roles.Admin }
}
})).Succeeded) {
var result = _categoryItemService.Delete(siteId, categoryId);
return result.ToActionResult();

View File

@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authorization;
using DomainResults.Mvc;
using WeatherForecast.Services;
using WeatherForecast.Models.CategoryItem.Requests;
namespace WeatherForecast.Controllers;
@ -36,24 +37,13 @@ public class CategoryItemsController : ControllerBase {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="locale"></param>
/// <param name="reuestData"></param>
/// <returns></returns>
[HttpGet("{siteId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] string? locale) {
var result = _categoryItemsService.Get(siteId, locale);
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetCategoryItemsRequestModel reuestData) {
var result = _categoryItemsService.Get(siteId, reuestData);
return result.ToActionResult();
}
#endregion
//[HttpDelete("{siteId}")]
//public async Task<IActionResult> Delete([FromRoute] Guid siteId) {
// if ((await _authorizationService.AuthorizeAsync(User, null, new CategoryAuthorizationRequirement(true, CrudActions.Delete))).Succeeded) {
// var result = _categoryItemsService.Delete(siteId);
// return result.ToActionResult();
// }
// else {
// return Unauthorized();
// }
//}
}

View File

@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authorization;
using DomainResults.Mvc;
using WeatherForecast.Services;
using WeatherForecast.Models.Content.Requests;
namespace WeatherForecast.Controllers;
@ -34,10 +35,12 @@ public class ContentController : ControllerBase {
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpGet("{siteId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] string? locale) {
var result = _contentService.GetContent(siteId, locale ?? "en-US") ;
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetContentRequestModel requestData) {
var result = _contentService.GetContent(siteId, requestData) ;
return result.ToActionResult();
}
#endregion

View File

@ -6,6 +6,8 @@ using DomainResults.Mvc;
using DataProviders.Buckets;
using WeatherForecast.Services;
using WeatherForecast.Policies;
using DomainObjects.Documents.Users;
namespace WeatherForecast.Controllers;
@ -18,18 +20,22 @@ public class DkimController : ControllerBase {
private readonly IAuthorizationService _authorizationService;
private readonly IDkimBucketDataProvider _dkimBucketDataProvider;
private readonly IDkimService _dkimService;
/// <summary>
///
/// </summary>
/// <param name="authorizationService"></param>
/// <param name="dkimBucketDataProvider"></param>
/// <param name="dkimService"></param>
public DkimController(
IAuthorizationService authorizationService,
IDkimBucketDataProvider dkimBucketDataProvider,
IDkimService dkimService
) {
_authorizationService = authorizationService;
_dkimBucketDataProvider = dkimBucketDataProvider;
_dkimService = dkimService;
}
@ -37,20 +43,31 @@ public class DkimController : ControllerBase {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="file"></param>
/// <param name="formFile"></param>
/// <returns></returns>
[HttpPost("{siteId}")]
public IActionResult Post([FromRoute] Guid siteId, IFormFile file) {
public async Task<IActionResult> Post([FromRoute] Guid siteId, IFormFile formFile) {
if (!(file.Length > 0))
if (!(formFile.Length > 0))
return IDomainResult.Failed().ToActionResult();
using var ms = new MemoryStream();
file.CopyTo(ms);
formFile.CopyTo(ms);
var result = _dkimService.Post(new BucketFile(siteId, file.FileName, ms.ToArray(), file.ContentType));
var newFile = new BucketFile(Guid.NewGuid(), siteId, formFile.FileName, ms.ToArray(), formFile.ContentType);
return result.ToActionResult();
var authorizationResult = await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { newFile }, new DkimAuthorisationRequirement {
Roles = new List<DkimRole> {
new DkimRole { Role = Roles.Admin }
}
});
if(authorizationResult.Succeeded ) {
var result = _dkimService.Post(newFile);
return result.ToActionResult();
}
return Unauthorized();
}
/// <summary>
@ -60,9 +77,23 @@ public class DkimController : ControllerBase {
/// <param name="fileId"></param>
/// <returns></returns>
[HttpDelete("{siteId}/{fileId}")]
public IActionResult Delete([FromRoute] Guid siteId, [FromRoute] Guid fileId) {
public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid fileId) {
var result = _dkimService.Delete(siteId, fileId);
return result.ToActionResult();
var (file, fileDownloadResult) = _dkimBucketDataProvider.Download(siteId, fileId);
if (!fileDownloadResult.IsSuccess || file == null)
return fileDownloadResult.ToActionResult();
var authorizationResult = await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { file }, new DkimAuthorisationRequirement {
Roles = new List<DkimRole> {
new DkimRole { Role = Roles.Admin }
}
});
if (authorizationResult.Succeeded) {
var result = _dkimService.Delete(siteId, fileId);
return result.ToActionResult();
}
return Unauthorized();
}
}

View File

@ -1,111 +0,0 @@
using Core.Enumerations;
using DataProviders.Buckets;
using DomainResults.Common;
using DomainResults.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WeatherForecast.Policies;
namespace WeatherForecast.Controllers;
/// <summary>
///
/// </summary>
[AllowAnonymous]
[Route("api/[controller]")]
public class FileController : ControllerBase {
private readonly IAuthorizationService _authorizationService;
private readonly IImageBucketDataProvider _imageBucketDataProvider;
/// <summary>
///
/// </summary>
/// <param name="authorizationService"></param>
/// <param name="imageBucketDataProvider"></param>
public FileController(
IAuthorizationService authorizationService,
IImageBucketDataProvider imageBucketDataProvider
) {
_authorizationService = authorizationService;
_imageBucketDataProvider = imageBucketDataProvider;
}
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="file"></param>
/// <returns></returns>
[HttpPost("{siteId}/{userId}")]
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromRoute] Guid userId, IFormFile file) {
if (!(file.Length > 0))
return IDomainResult.Failed().ToActionResult();
using var ms = new MemoryStream();
file.CopyTo(ms);
var newFile = new BucketFile(Guid.NewGuid(), siteId, userId, file.FileName, ms.ToArray(), file.ContentType);
if ((await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { newFile }, new FileAuthorisationRequirement {
Action = CrudActions.Create
})).Succeeded) {
var result = _imageBucketDataProvider.Upload(newFile);
return result.ToActionResult();
}
return Unauthorized();
}
/// <summary>
/// https://www.c-sharpcorner.com/article/fileresult-in-asp-net-core-mvc2/
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
[HttpGet("{siteId}/{userId}/{fileId}")]
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] Guid fileId) {
var (file, result) = _imageBucketDataProvider.Download(siteId, userId, fileId);
if (!result.IsSuccess || file == null)
return result.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { file }, new FileAuthorisationRequirement {
Action = CrudActions.Read
})).Succeeded) {
var stream = new MemoryStream(file.Bytes);
return new FileStreamResult(stream, file.ContentType) {
FileDownloadName = file.Name
};
}
return Unauthorized();
}
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
[HttpDelete("{siteId}/{userId}/{fileId}")]
public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] Guid fileId) {
var (file, fileDownloadResult) = _imageBucketDataProvider.Download(siteId, userId, fileId);
if (!fileDownloadResult.IsSuccess || file == null)
return fileDownloadResult.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { file }, new FileAuthorisationRequirement {
Action = CrudActions.Delete
})).Succeeded) {
var result = _imageBucketDataProvider.DeleteOne(siteId, userId, fileId);
return result.ToActionResult();
}
return Unauthorized();
}
}

View File

@ -3,6 +3,11 @@ using Microsoft.AspNetCore.Authorization;
using WeatherForecast.Services;
using DomainResults.Mvc;
using Core.Enumerations;
using DataProviders.Buckets;
using DomainResults.Common;
using WeatherForecast.Policies;
using DomainObjects.Documents.Users;
namespace WeatherForecast.Controllers;
@ -14,24 +19,121 @@ namespace WeatherForecast.Controllers;
public class ImageController : ControllerBase {
private readonly IAuthorizationService _authorizationService;
private readonly IImageBucketDataProvider _imageBucketDataProvider;
private readonly IImageService _imageService;
/// <summary>
///
/// </summary>
/// <param name="authorizationService"></param>
/// <param name="imageBucketDataProvider"></param>
/// <param name="imgeService"></param>
public ImageController(
IAuthorizationService authorizationService,
IImageBucketDataProvider imageBucketDataProvider,
IImageService imgeService
) {
_authorizationService = authorizationService;
_imageBucketDataProvider = imageBucketDataProvider;
_imageService = imgeService;
}
#region Authless methods
#region Post
/// <summary>
///
/// Site wide<br />
/// Allowed: Admin, Shop Manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="formFile"></param>
/// <returns></returns>
[HttpPost("{siteId}")]
public async Task<IActionResult> Post([FromRoute] Guid siteId, IFormFile formFile) =>
await PostCore(siteId, null, formFile);
/// <summary>
/// Site user specific<br />
/// Allowed: Admin, Editor, Author, Contributor, Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="formFile"></param>
/// <returns></returns>
[HttpPost("{siteId}/{userId}")]
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromRoute] Guid userId, IFormFile formFile) =>
await PostCore(siteId, userId, formFile);
private async Task<IActionResult> PostCore(Guid siteId, Guid? userId, IFormFile formFile) {
if (!(formFile.Length > 0))
return IDomainResult.Failed().ToActionResult();
using var ms = new MemoryStream();
formFile.CopyTo(ms);
var newFile = new BucketFile(Guid.NewGuid(), siteId, formFile.FileName, ms.ToArray(), formFile.ContentType);
if (userId != null)
newFile.UserId = userId;
var authorizationResult = await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { newFile }, new ImageAuthorisationRequirement {
Action = CrudActions.Create,
Roles = new List<ImageRole> {
new ImageRole { Role = Roles.Admin },
new ImageRole { Role = Roles.Editor },
new ImageRole { Role = Roles.Author, OwnOnly = true },
new ImageRole { Role = Roles.Contributor, OwnOnly = true },
new ImageRole { Role = Roles.ShopManager }
}
});
if (authorizationResult.Succeeded) {
var result = _imageService.Post(newFile);
return result.ToActionResult();
}
return Unauthorized();
}
#endregion
#region Get
/// <summary>
/// Site user specific<br />
/// Allowed: Admin, Editor, Author (own), Contributor (own), Shop manager
/// https://www.c-sharpcorner.com/article/fileresult-in-asp-net-core-mvc2/
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
[HttpGet("{siteId}/{userId}/{fileId}")]
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] Guid fileId) {
var (file, result) = _imageBucketDataProvider.Download(siteId, userId, fileId);
if (!result.IsSuccess || file == null)
return result.ToActionResult();
var authorizationResult = await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { file }, new ImageAuthorisationRequirement {
Action = CrudActions.Read,
Roles = new List<ImageRole> {
new ImageRole { Role = Roles.Admin },
new ImageRole { Role = Roles.Editor },
new ImageRole { Role = Roles.Author, OwnOnly = true },
new ImageRole { Role = Roles.Contributor, OwnOnly = true },
new ImageRole { Role = Roles.ShopManager }
}
});
if (authorizationResult.Succeeded) {
var stream = new MemoryStream(file.Bytes);
return new FileStreamResult(stream, file.ContentType) {
FileDownloadName = file.Name
};
}
return Unauthorized();
}
/// <summary>
/// Site specific<br />
/// Allowed everyone
/// </summary>
/// <param name="siteId"></param>
/// <param name="width"></param>
@ -53,4 +155,114 @@ public class ImageController : ControllerBase {
}
#endregion
#region Update
/// <summary>
/// Site specific<br />
/// Allowed Admin, Shop Manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="fileId"></param>
/// <param name="formFile"></param>
/// <returns></returns>
[HttpPost("{siteId}/{fileId}")]
public async Task<IActionResult> Update([FromRoute] Guid siteId, [FromRoute] Guid fileId, IFormFile formFile) =>
await UpdateCore(siteId, null, fileId, formFile);
/// <summary>
/// Can Admin, Editor, Author (own), Contributor (own, not yet pubblished), Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <param name="formFile"></param>
/// <returns></returns>
[HttpPost("{siteId}/{userId}/{fileId}")]
public async Task<IActionResult> Update([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] Guid fileId, IFormFile formFile) =>
await UpdateCore(siteId, userId, fileId, formFile);
private async Task<IActionResult> UpdateCore(Guid siteId, Guid? userId, Guid fileId, IFormFile formFile) {
var (file, getFileResult) = _imageBucketDataProvider.Download(siteId, userId, fileId);
if (!getFileResult.IsSuccess || file == null)
return getFileResult.ToActionResult();
if (!(formFile.Length > 0))
return IDomainResult.Failed().ToActionResult();
using var ms = new MemoryStream();
formFile.CopyTo(ms);
var newFile = new BucketFile(fileId, siteId, formFile.FileName, ms.ToArray(), formFile.ContentType);
if(userId != null)
newFile.UserId = userId;
var authorizationResult = await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { file }, new ImageAuthorisationRequirement {
Action = CrudActions.Update,
Roles = new List<ImageRole> {
new ImageRole { Role = Roles.Admin },
new ImageRole { Role = Roles.Editor },
new ImageRole { Role = Roles.Author, OwnOnly = true },
new ImageRole { Role = Roles.Contributor, OwnOnly = true, DenyPublished = true },
new ImageRole { Role = Roles.ShopManager }
}
});
if (authorizationResult.Succeeded) {
var result = _imageService.Update(siteId, userId, fileId, newFile);
return result.ToActionResult();
}
return Unauthorized();
}
#endregion
#region Delete
/// <summary>
/// Cross site media
/// Can Admin, Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
[HttpDelete("{siteId}/{fileId}")]
public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid fileId) =>
await DeleteCore(siteId, null, fileId);
/// <summary>
/// Can Admin, Editor, Author (own), Contributor (own, not yet pubblished), Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
[HttpDelete("{siteId}/{userId}/{fileId}")]
public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] Guid fileId) =>
await DeleteCore(siteId, userId, fileId);
private async Task<IActionResult> DeleteCore(Guid siteId, Guid? userId, Guid fileId) {
var (file, fileDownloadResult) = _imageBucketDataProvider.Download(siteId, userId, fileId);
if (!fileDownloadResult.IsSuccess || file == null)
return fileDownloadResult.ToActionResult();
var authorizationResult = await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { file }, new ImageAuthorisationRequirement {
Action = CrudActions.Delete,
Roles = new List<ImageRole> {
new ImageRole { Role = Roles.Admin },
new ImageRole { Role = Roles.Editor },
new ImageRole { Role = Roles.Author, OwnOnly = true },
new ImageRole { Role = Roles.Contributor, OwnOnly = true, DenyPublished = true },
new ImageRole { Role = Roles.ShopManager }
}
});
if (authorizationResult.Succeeded) {
var result = _imageService.Delete(siteId, userId, fileId);
return result.ToActionResult();
}
return Unauthorized();
}
#endregion
}

View File

@ -1,11 +1,13 @@
using Core.Enumerations;
using DataProviders;
using DataProviders.Buckets;
using DomainObjects.Documents.Users;
using DomainResults.Common;
using DomainResults.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WeatherForecast.Policies;
using WeatherForecast.Services;
namespace WeatherForecast.Controllers;
@ -14,22 +16,26 @@ namespace WeatherForecast.Controllers;
/// </summary>
[AllowAnonymous]
[Route("api/[controller]")]
public class FilesController : ControllerBase {
public class ImagesController : ControllerBase {
private readonly IAuthorizationService _authorizationService;
private readonly IImageBucketDataProvider _imageBucketDataProvider;
private readonly IImageService _imageService;
/// <summary>
///
/// </summary>
/// <param name="authorizationService"></param>
/// <param name="imageBucketDataProvider"></param>
public FilesController(
/// <param name="imageService"></param>
public ImagesController(
IAuthorizationService authorizationService,
IImageBucketDataProvider imageBucketDataProvider
IImageBucketDataProvider imageBucketDataProvider,
IImageService imageService
) {
_authorizationService = authorizationService;
_imageBucketDataProvider = imageBucketDataProvider;
_imageService = imageService;
}
/// <summary>
@ -40,7 +46,10 @@ public class FilesController : ControllerBase {
/// <param name="file"></param>
/// <returns></returns>
[HttpPost("{siteId}/{userId}")]
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromRoute] Guid userId, List<IFormFile> file) {
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromRoute] Guid userId, List<IFormFile> file) =>
await PostCore(siteId, userId, file);
private async Task<IActionResult> PostCore(Guid siteId, Guid? userId, List<IFormFile> file) {
if (file.Any(x => !(x.Length > 0)))
return IDomainResult.Failed().ToActionResult();
@ -48,36 +57,31 @@ public class FilesController : ControllerBase {
var newFiles = file.Select(x => {
using var ms = new MemoryStream();
x.CopyTo(ms);
return new BucketFile(Guid.NewGuid(), siteId, userId, x.FileName, ms.ToArray(), x.ContentType);
var newFile = new BucketFile(Guid.NewGuid(), siteId, x.FileName, ms.ToArray(), x.ContentType);
if (userId != null)
newFile.UserId = userId;
return newFile;
}).ToList();
if ((await _authorizationService.AuthorizeAsync(User, newFiles, new FileAuthorisationRequirement {
Action = CrudActions.Create
})).Succeeded) {
var result = _imageBucketDataProvider.UploadMany(newFiles);
var authorizationResult = await _authorizationService.AuthorizeAsync(User, newFiles, new ImageAuthorisationRequirement {
Action = CrudActions.Create,
Roles = new List<ImageRole> {
new ImageRole { Role = Roles.Admin },
new ImageRole { Role = Roles.Editor },
new ImageRole { Role = Roles.Author, OwnOnly = true },
new ImageRole { Role = Roles.Contributor, OwnOnly = true },
new ImageRole { Role = Roles.ShopManager }
}
});
if (authorizationResult.Succeeded) {
var result = _imageService.Post(newFiles);
return result.ToActionResult();
}
return Unauthorized();
}
//[HttpDelete("{siteId}/{userId}")]
//public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromBody] FileRequestModel requestData) {
// var (files, fileDownloadResult) = _imageBucketDataProvider.DownloadMany(siteId, userId, requestData.Ids);
// if (!fileDownloadResult.IsSuccess || files == null)
// return fileDownloadResult.ToActionResult();
// if ((await _authorizationService.AuthorizeAsync(User, files, new FileAuthorisationRequirement {
// WhiteListToken = true,
// SameAuthor = true,
// Action = CrudActions.Delete
// })).Succeeded) {
// var result = _imageBucketDataProvider.DeletMany(siteId, userId);
// return result.ToActionResult();
// }
// return Unauthorized();
//}
}

View File

@ -31,7 +31,7 @@ public class InitializationController : ControllerBase {
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPost]
public IActionResult InitializeSystem([FromBody] InitializeSystemRequestModel requestData) {
public IActionResult InitializeSystem([FromBody] PostInitializeSystemRequestModel requestData) {
var result = _initializationService.InitializeSystem(requestData);
return result.ToActionResult();

View File

@ -8,7 +8,7 @@ using WeatherForecast.Policies;
using Core.Enumerations;
using DataProviders.Collections;
using DomainObjects.Documents;
using WeatherForecast.Models.Shop.Requests;
using WeatherForecast.Models.ShopCart.Requests;
namespace WeatherForecast.Controllers;
@ -49,9 +49,10 @@ public class ShopCartItemController : ControllerBase {
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPost("{siteId}/{userId}/{sku}")]
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] string sku, [FromBody] ShopCartItemRequestModel requestData) {
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] string sku, [FromBody] PostShopCartItemRequestModel requestData) {
if ((await _authorizationService.AuthorizeAsync(User, null, new ShopCartAuthorizationRequirement {
Action = CrudActions.Create
Action = CrudActions.Create,
})).Succeeded) {
var result = _shopCartItemService.Post(siteId, userId, sku, requestData);
return result.ToActionResult();
@ -63,9 +64,13 @@ public class ShopCartItemController : ControllerBase {
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="sku"></param>
/// <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] string? locale) {
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] string sku, [FromQuery] GetShopCartItemRequestModel requestData) {
var (cartItem, getCartItemResult) = _shopCartDataProvider.Get(siteId, userId, sku);
if (!getCartItemResult.IsSuccess || cartItem == null)
@ -74,7 +79,7 @@ public class ShopCartItemController : ControllerBase {
if ((await _authorizationService.AuthorizeAsync(User, new List<ShopCartDocument> { cartItem }, new ShopCartAuthorizationRequirement {
Action = CrudActions.Read
})).Succeeded) {
var result = _shopCartItemService.Get(cartItem, locale);
var result = _shopCartItemService.Get(cartItem, requestData);
return result.ToActionResult();
}
@ -90,7 +95,7 @@ public class ShopCartItemController : ControllerBase {
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPut("{siteId}/{userId}/{sku}")]
public async Task<IActionResult> Update([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] string sku, [FromBody] ShopCartItemRequestModel requestData) {
public async Task<IActionResult> Update([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] string sku, [FromBody] PutShopCartItemRequestModel requestData) {
var (cartItem, getCartItemResult) = _shopCartDataProvider.Get(siteId, userId, sku);
if (!getCartItemResult.IsSuccess || cartItem == null)

View File

@ -7,6 +7,7 @@ using WeatherForecast.Services;
using WeatherForecast.Policies;
using Core.Enumerations;
using DataProviders.Collections;
using WeatherForecast.Models.ShopCart.Requests;
namespace WeatherForecast.Controllers;
@ -42,7 +43,7 @@ public class ShopCartItemsController : ControllerBase {
/// </summary>
/// <returns></returns>
[HttpGet("{siteId}/{userId}")]
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromQuery] string? locale) {
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromQuery] GetShopCartItemsController requestData) {
var (cartItems, getCartItemsResult) = _shopCartDataProvider.GetAll(siteId, userId);
if (!getCartItemsResult.IsSuccess || cartItems == null)
@ -51,26 +52,10 @@ public class ShopCartItemsController : ControllerBase {
if ((await _authorizationService.AuthorizeAsync(User, cartItems, new ShopCartAuthorizationRequirement {
Action = CrudActions.Read
})).Succeeded) {
var result = _shopCartItemsService.Get(cartItems, locale);
var result = _shopCartItemsService.Get(cartItems, requestData);
return result.ToActionResult();
}
return Unauthorized();
}
//[HttpDelete("{siteId}/{userId}")]
//public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid userId) {
// if ((await _authorizationService.AuthorizeAsync(User, null, new ShopCartAuthorizationRequirement {
// WhiteListToken = true,
// SameAuthor = true,
// Action = CrudActions.Delete
// })).Succeeded) {
// var result = _shopCartItemsService.Delete(siteId, userId);
// return result.ToActionResult();
// }
// return Unauthorized();
//}
}

View File

@ -11,6 +11,7 @@ using DataProviders.Collections;
using DomainResults.Common;
using Extensions;
using DomainObjects.Documents.Posts;
using DomainObjects.Documents.Users;
namespace WeatherForecast.Controllers;
@ -56,14 +57,14 @@ public class ShopItemController : ControllerBase {
#endregion
/// <summary>
///
/// Can Admin, Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="sku"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPost("{siteId}/{sku}")]
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromRoute] string sku, [FromBody] ShopItemRequestModel requestData) {
public async Task<IActionResult> Post([FromRoute] Guid siteId, [FromRoute] string sku, [FromBody] PostShopItemRequestModel requestData) {
var userId = User?.Identity?.Name?.ToNullableGuid();
if (userId == null)
@ -72,7 +73,11 @@ public class ShopItemController : ControllerBase {
var shopItem = requestData.ToDomainObject(sku, userId.Value, siteId);
if ((await _authorizationService.AuthorizeAsync(User, new List<ShopDocument> { shopItem }, new ShopAuthorizationRequirement {
Action = CrudActions.Create
Action = CrudActions.Create,
Roles = new List<ShopRole> {
new ShopRole { Role = Roles.Admin },
new ShopRole { Role = Roles.ShopManager }
}
})).Succeeded) {
var result = _shopItemService.Post(shopItem);
@ -84,6 +89,7 @@ public class ShopItemController : ControllerBase {
/// <summary>
/// Returns full object
/// Can Admin, Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="sku"></param>
@ -96,7 +102,11 @@ public class ShopItemController : ControllerBase {
return getShopItemResult.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<ShopDocument> { shopItem }, new ShopAuthorizationRequirement {
Action = CrudActions.Read
Action = CrudActions.Read,
Roles = new List<ShopRole> {
new ShopRole { Role = Roles.Admin },
new ShopRole { Role = Roles.ShopManager }
}
})).Succeeded) {
var result = _shopItemService.Get(shopItem);
return result.ToActionResult();
@ -106,21 +116,25 @@ public class ShopItemController : ControllerBase {
}
/// <summary>
///
/// Can Admin, Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="sku"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPut("{siteId}/{sku}")]
public async Task<IActionResult> Update([FromRoute] Guid siteId, [FromRoute] string sku, [FromBody] ShopItemRequestModel requestData) {
public async Task<IActionResult> Update([FromRoute] Guid siteId, [FromRoute] string sku, [FromBody] PutShopItemRequestModel requestData) {
var (shopItem, getShopItemResult) = _shopCatalogDataProvider.Get(siteId, sku);
if (!getShopItemResult.IsSuccess || shopItem == null)
return getShopItemResult.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<ShopDocument> { shopItem }, new ShopAuthorizationRequirement {
Action = CrudActions.Update
Action = CrudActions.Update,
Roles = new List<ShopRole> {
new ShopRole { Role = Roles.Admin },
new ShopRole { Role = Roles.ShopManager }
}
})).Succeeded) {
var result = _shopItemService.Update(siteId, sku, requestData);
return result.ToActionResult();
@ -130,7 +144,7 @@ public class ShopItemController : ControllerBase {
}
/// <summary>
///
/// Can Admin, Shop manager
/// </summary>
/// <param name="siteId"></param>
/// <param name="sku"></param>
@ -143,7 +157,11 @@ public class ShopItemController : ControllerBase {
return getShopItemResult.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<ShopDocument> { shopItem }, new ShopAuthorizationRequirement {
Action = CrudActions.Delete
Action = CrudActions.Delete,
Roles = new List<ShopRole> {
new ShopRole { Role = Roles.Admin },
new ShopRole { Role = Roles.ShopManager }
}
})).Succeeded) {
var result = _shopCatalogDataProvider.Delete(shopItem.Id);
return result.ToActionResult();

View File

@ -5,6 +5,7 @@ using DomainResults.Mvc;
using WeatherForecast.Services;
using DataProviders.Collections;
using WeatherForecast.Models.Shop.Requests;
namespace WeatherForecast.Controllers;
@ -40,27 +41,12 @@ public class ShopItemsController : ControllerBase {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="category"></param>
/// <param name="currentPage"></param>
/// <param name="itemsPerPage"></param>
/// <param name="locale"></param>
/// <param name="searchText"></param>
/// <param name="requestData"></param>
/// <returns></returns>
[HttpGet("{siteId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] Guid? category, [FromQuery] int? currentPage, [FromQuery] int? itemsPerPage, [FromQuery] string? locale, [FromQuery] string? searchText) {
var result = _shopItemsService.Get(siteId, category, currentPage ?? 1, itemsPerPage ?? 8, locale, searchText);
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetShopItemsRequestModel requestData) {
var result = _shopItemsService.Get(siteId, requestData);
return result.ToActionResult();
}
#endregion
//[HttpDelete("{siteId}")]
//public async Task<IActionResult> Delete([FromRoute] Guid siteId) {
// if ((await _authorizationService.AuthorizeAsync(User, null, new CrudActionRequirement(_webapiController, CrudActions.Create))).Succeeded) {
// var result = _shopItemsService.Delete(siteId);
// return result.ToActionResult();
// }
// return Unauthorized();
//}
}

View File

@ -9,6 +9,9 @@ using DataProviders.Buckets;
using WeatherForecast.Services;
using WeatherForecast.Models.Template.Requests;
using Core.Binders;
using Core.Enumerations;
using DomainObjects.Documents.Users;
using WeatherForecast.Policies;
namespace WeatherForecast.Controllers;
@ -21,18 +24,22 @@ public class TemplateController : ControllerBase {
private readonly IAuthorizationService _authorizationService;
private readonly ITemplateBucketDataProvider _templateBucketDataProvider;
private readonly ITemplateService _templateService;
/// <summary>
///
/// </summary>
/// <param name="authorizationService"></param>
/// <param name="templateBucketDataProvider"></param>
/// <param name="templateService"></param>
public TemplateController(
IAuthorizationService authorizationService,
ITemplateBucketDataProvider templateBucketDataProvider,
ITemplateService templateService
) {
_authorizationService = authorizationService;
_templateBucketDataProvider = templateBucketDataProvider;
_templateService = templateService;
}
@ -41,20 +48,32 @@ public class TemplateController : ControllerBase {
/// </summary>
/// <param name="siteId"></param>
/// <param name="requestData"></param>
/// <param name="file"></param>
/// <param name="formFile"></param>
/// <returns></returns>
[HttpPost("{siteId}")]
public IActionResult Post([FromRoute] Guid siteId, [ModelBinder(typeof(JsonModelBinder<PostTemplateRequestModel>))] PostTemplateRequestModel requestData, IFormFile file) {
public async Task<IActionResult> Post([FromRoute] Guid siteId, [ModelBinder(typeof(JsonModelBinder<PostTemplateRequestModel>))] PostTemplateRequestModel? requestData, IFormFile formFile) {
if (!(file.Length > 0))
if (!(formFile.Length > 0))
return IDomainResult.Failed().ToActionResult();
using var ms = new MemoryStream();
file.CopyTo(ms);
formFile.CopyTo(ms);
var result = _templateService.Post(requestData, new BucketFile(siteId, file.FileName, ms.ToArray(), file.ContentType));
var newFile = new BucketFile(siteId, formFile.FileName, ms.ToArray(), formFile.ContentType);
return result.ToActionResult();
var authorizationResult = await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { newFile }, new TemplateAuthorisationRequirement {
Action = CrudActions.Create,
Roles = new List<TemplateRole> {
new TemplateRole { Role = Roles.Admin }
}
});
if (authorizationResult.Succeeded) {
var result = _templateService.Post(newFile);
return result.ToActionResult();
}
return Unauthorized();
}
/// <summary>
@ -64,8 +83,27 @@ public class TemplateController : ControllerBase {
/// <param name="fileId"></param>
/// <returns></returns>
[HttpGet("{siteId}/{fileId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromRoute] Guid fileId) {
return BadRequest();
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid fileId) {
var (file, result) = _templateBucketDataProvider.Download(siteId, fileId);
if (!result.IsSuccess || file == null)
return result.ToActionResult();
var authorizationResult = await _authorizationService.AuthorizeAsync(User, new List<BucketFile> { file }, new TemplateAuthorisationRequirement {
Action = CrudActions.Read,
Roles = new List<TemplateRole> {
new TemplateRole { Role = Roles.Admin }
}
});
if (authorizationResult.Succeeded) {
var stream = new MemoryStream(file.Bytes);
return new FileStreamResult(stream, file.ContentType) {
FileDownloadName = file.Name
};
}
return Unauthorized();
}
/// <summary>
@ -77,7 +115,7 @@ public class TemplateController : ControllerBase {
/// <param name="file"></param>
/// <returns></returns>
[HttpGet("{siteId}/{fileId}")]
public IActionResult Put([FromRoute] Guid siteId, [FromRoute] Guid fileId, [ModelBinder(typeof(JsonModelBinder<PostTemplateRequestModel>))] PostTemplateRequestModel requestData, IFormFile file) {
public IActionResult Put([FromRoute] Guid siteId, [FromRoute] Guid fileId, [ModelBinder(typeof(JsonModelBinder<PutTemplateRequestModel>))] PutTemplateRequestModel requestData, IFormFile file) {
return BadRequest();
}

View File

@ -34,7 +34,7 @@ public class UtilsController : ControllerBase {
/// <param name="requestData"></param>
/// <returns></returns>
[HttpPost("[action]")]
public IActionResult EncryptStringAes([FromBody] EncryptStringAesRequestModel requestData) {
public IActionResult EncryptStringAes([FromBody] PostEncryptStringAesRequestModel requestData) {
var result = AesService.EncryptString(requestData.IV, requestData.Key, requestData.InputString);
if(result != null)
return Ok(result);
@ -42,5 +42,14 @@ public class UtilsController : ControllerBase {
return BadRequest();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
[HttpGet("[action]")]
public IActionResult GenerateGuid() {
return Ok(Guid.NewGuid());
}
}

View File

@ -26,8 +26,8 @@ public class WeatherForecastController : ControllerBase {
/// </summary>
/// <returns></returns>
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecastResponseModel> Get() {
return Enumerable.Range(1, 5).Select(index => new WeatherForecastResponseModel {
public IEnumerable<GetWeatherForecastResponseModel> Get() {
return Enumerable.Range(1, 5).Select(index => new GetWeatherForecastResponseModel {
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]

View File

@ -1,72 +0,0 @@
using Core.Abstractions;
using Core.Abstractions.Models;
using DomainObjects.L10n;
using Core.Enumerations;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using DomainObjects.Enumerations;
namespace WeatherForecast.Models.Abstractions.PostItem.Requests {
/// <summary>
///
/// </summary>
public class MediaAttachmentL10nModel : RequestModelBase<MediaAttachmentL10n> {
/// <summary>
///
/// </summary>
public string? Locale { 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>
/// <returns></returns>
public MediaAttachmentL10n ToDomainObject() {
if (HasValidationErrors()) throw new ValidationException();
return new MediaAttachmentL10n() {
Locale = Enumeration.FromDisplayName<Locales>(Locale),
Alt = Alt
};
}
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Locale))
yield return new ValidationResult($"{nameof(Locale)} {Errors.NullOrWhiteSpace.Name}");
else if (Enumeration.FromDisplayName<Locales>(Locale) == null)
yield return new ValidationResult($"{nameof(Locale)} {Errors.WrongOrNotManaged}");
if (string.IsNullOrWhiteSpace(Alt))
yield return new ValidationResult($"{nameof(Alt)} {Errors.NullOrWhiteSpace.Name}");
}
[MemberNotNullWhen(false, new[] { nameof(Locale), nameof(Alt) })]
private bool HasValidationErrors() => Validate(new ValidationContext(this)).Any();
}
}

View File

@ -1,62 +0,0 @@
using Core.Abstractions;
using Core.Abstractions.Models;
using DomainObjects;
using Core.Enumerations;
using Extensions;
using System.ComponentModel.DataAnnotations;
using DomainObjects.Enumerations;
namespace WeatherForecast.Models.Abstractions.PostItem.Requests {
/// <summary>
///
/// </summary>
public class MediaAttachmentRequestModel : RequestModelBase<MediaAttachment> {
/// <summary>
///
/// </summary>
public string? Src { get; set; }
/// <summary>
///
/// </summary>
public string? MediaType { get; set; }
/// <summary>
///
/// </summary>
public List<MediaAttachmentL10nModel>? L10n { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public MediaAttachment ToDomainObject() {
return new MediaAttachment {
Src = Src,
MediaType = Enumeration.FromDisplayName<MediaTypes>(MediaType),
L10n = L10n.Select(x => x.ToDomainObject()).ToList()
};
}
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Src))
yield return new ValidationResult($"{nameof(Src)} {Errors.NullOrWhiteSpace}");
if (string.IsNullOrWhiteSpace(MediaType))
yield return new ValidationResult($"{nameof(MediaType)} {Errors.NullOrWhiteSpace}");
if (L10n.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(L10n)} {Errors.NullOrEmpty}");
}
}
}

View File

@ -1,120 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using Core.Abstractions;
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Enumerations;
using DomainObjects.L10n;
namespace WeatherForecast.Models.Abstractions.PostItem.Requests {
/// <summary>
///
/// </summary>
public class PostItemL10nModel : RequestModelBase<PostItemL10n> {
/// <summary>
///
/// </summary>
public string? Locale { 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 string? TextFormat { get; set; }
/// <summary>
///
/// </summary>
public List<string>? Badges { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public PostItemL10n ToDomainObject() {
if (HasValidationErrors()) throw new ValidationException();
return new PostItemL10n() {
Locale = Enumeration.FromDisplayName<Locales>(Locale),
Slug = Slug,
Description = Description,
Title = Title,
Text = Text,
ShortText = ShortText,
// TODO: create plain text creation logic
PlainText = "TODO",
TextFormat = Enumeration.FromDisplayName<TextFormat>(TextFormat),
Badges = Badges
};
}
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Locale))
yield return new ValidationResult($"{nameof(Locale)} {Errors.NullOrWhiteSpace.Name}");
else if (Enumeration.FromDisplayName<Locales>(Locale) == null)
yield return new ValidationResult($"{nameof(Locale)} {Errors.WrongOrNotManaged}");
if (string.IsNullOrWhiteSpace(Slug))
yield return new ValidationResult($"{nameof(Slug)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(Description))
yield return new ValidationResult($"{nameof(Description)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(Title))
yield return new ValidationResult($"{nameof(Title)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(Text))
yield return new ValidationResult($"{nameof(Text)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(ShortText))
yield return new ValidationResult($"{nameof(ShortText)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(TextFormat))
yield return new ValidationResult($"{nameof(TextFormat)} {Errors.NullOrWhiteSpace.Name}");
else if (Enumeration.FromDisplayName<TextFormat>(TextFormat) == null)
yield return new ValidationResult($"{nameof(TextFormat)} {Errors.WrongOrNotManaged}");
}
[MemberNotNullWhen(false, new[] { nameof(Locale), nameof(Slug), nameof(Description), nameof(Title), nameof(Text), nameof(ShortText), nameof(TextFormat) })]
private bool HasValidationErrors() => Validate(new ValidationContext(this)).Any();
}
}

View File

@ -1,36 +0,0 @@
using Core.Abstractions.Models;
namespace WeatherForecast.Models.Abstractions.PostItem.Requests {
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class PostItemRequestModelBase<T> : RequestModelBase<T> {
/// <summary>
///
/// </summary>
public List<PostItemL10nModel>? L10n { get; set; }
/// <summary>
///
/// </summary>
public List<MediaAttachmentRequestModel>? MediaAttachments { get; set; }
/// <summary>
///
/// </summary>
public List<Guid>? Categories { get; set; }
/// <summary>
///
/// </summary>
public List<string>? Tags { get; set; }
/// <summary>
///
/// </summary>
public bool? FamilyFriendly { get; set; }
}
}

View File

@ -96,7 +96,7 @@ namespace WeatherForecast.Models.Abstractions.PostItem.Responses
/// <summary>
///
/// </summary>
public List<CategoryItemResponseModel>? Categories { get; set; }
public List<GetCategoryItemResponseModel>? Categories { get; set; }
/// <summary>
///
@ -124,7 +124,7 @@ namespace WeatherForecast.Models.Abstractions.PostItem.Responses
/// <param name="categories"></param>
public PostItemResponseModelBase(PostItemBase<T> postItem, List<DomainObjects.Documents.Categories.Category> categories) : this(postItem) {
L10n = postItem.L10n.Select(x => new PostItemL10nModel(x)).ToList();
Categories = categories.Select(x => new CategoryItemResponseModel(x)).ToList();
Categories = categories.Select(x => new GetCategoryItemResponseModel(x)).ToList();
MediaAttachemnts = postItem.MediaAttachments?.Select(x => new MediaAttachmentResponseModel(x)).ToList();
}
@ -148,7 +148,7 @@ namespace WeatherForecast.Models.Abstractions.PostItem.Responses
Badges = postItemL10n.Badges;
}
Categories = categories.Select(x => new CategoryItemResponseModel(x, locale)).ToList();
Categories = categories.Select(x => new GetCategoryItemResponseModel(x, locale)).ToList();
MediaAttachemnts = postItem.MediaAttachments?.Select(x => new MediaAttachmentResponseModel(x, locale)).ToList();
}
}

View File

@ -6,7 +6,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// <summary>
///
/// </summary>
public class CreateAccountRequestModel : RequestModelBase {
public class PostAccountCreateRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -14,7 +14,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// <param name="validationContext"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
throw new NotImplementedException();
}
}

View File

@ -7,7 +7,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// <summary>
///
/// </summary>
public class AuthenticationRequestModel : RequestModelBase {
public class PostAuthenticationRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -24,7 +24,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if(string.IsNullOrWhiteSpace(Username))
yield return new ValidationResult($"{nameof(Username)} ${Errors.NullOrEmpty}");

View File

@ -1,12 +1,13 @@
using Core.Abstractions.Models;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using Core.Abstractions.Models;
namespace WeatherForecast.Models.Account.Requests {
/// <summary>
///
/// </summary>
public class RegisterRequestModel : RequestModelBase {
public class PutAccountConfirmRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -14,7 +15,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// <param name="validationContext"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
throw new NotImplementedException();
}
}

View File

@ -7,7 +7,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// <summary>
///
/// </summary>
public class PasswordChangeRequestModel : RequestModelBase {
public class PutPasswordChangeRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -24,7 +24,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(OldPassword))
yield return new ValidationResult($"{nameof(OldPassword)} ${Errors.NullOrEmpty}");

View File

@ -7,7 +7,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// <summary>
///
/// </summary>
public class PasswordRecoveryRequestModel : RequestModelBase {
public class PutPasswordRecoveryRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -19,7 +19,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Username))
yield return new ValidationResult($"{nameof(Username)} ${Errors.NullOrEmpty}");

View File

@ -7,7 +7,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// <summary>
///
/// </summary>
public class PasswordResetRequestModel : RequestModelBase {
public class PutPasswordResetRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -29,7 +29,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Token))
yield return new ValidationResult($"{nameof(Token)} ${Errors.NullOrEmpty}");

View File

@ -1,59 +0,0 @@
using Core.Enumerations;
using Extensions;
using System.ComponentModel.DataAnnotations;
using WeatherForecast.Models.Abstractions.PostItem.Requests;
using DomainObjects.Documents.Posts;
namespace WeatherForecast.Models.Blog.Requests
{
/// <summary>
///
/// </summary>
public class BlogItemRequestModel : PostItemRequestModelBase<BlogDocument> {
/// <summary>
///
/// </summary>
public uint? ReadTime { get; set; }
/// <summary>
///
/// </summary>
public uint? Likes { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public BlogDocument ToDomainObject(Guid userId, Guid siteId) => new () {
SiteId = siteId,
L10n = L10n.Select(x => x.ToDomainObject()).ToList(),
// Images
Author = userId,
Tags = Tags,
Categories = Categories,
FamilyFriendly = FamilyFriendly,
ReadTime = ReadTime,
Likes = Likes
};
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (L10n.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(L10n)} {Errors.NullOrEmpty}");
if (MediaAttachments.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(MediaAttachments)} {Errors.NullOrEmpty}");
}
}
}

View File

@ -0,0 +1,28 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.BlogItem.Requests {
/// <summary>
///
/// </summary>
public class GetBlogItemSlugRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public string Slug { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Slug))
yield return new ValidationResult($"{nameof(Slug)} {Errors.NullOrWhiteSpace.Name}");
}
}
}

View File

@ -0,0 +1,49 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Enumerations;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.BlogItem.Requests {
/// <summary>
///
/// </summary>
public class GetBlogItemsRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public Guid? Category { get; set; }
/// <summary>
///
/// </summary>
public string? SearchText { get; set; }
/// <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 (Locale == Locales.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse} {nameof(Locale)}");
}
}
}

View File

@ -0,0 +1,257 @@
using System.ComponentModel.DataAnnotations;
using DomainObjects.Documents.Posts;
using DomainObjects.Enumerations;
using DomainObjects.L10n;
using DomainObjects;
using Core.Enumerations;
using Core.Abstractions.Models;
namespace WeatherForecast.Models.Blog.Requests {
/// <summary>
///
/// </summary>
public class PostMediaAttachmentL10nRequestModel : RequestModelBase {
/// <summary>
///
/// </summary>
public Locales Locale { get; set; } = Locales.Unknown;
/// <summary>
///
/// </summary>
public string Alt { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string? Target { get; set; }
/// <summary>
///
/// </summary>
public string? Title { get; set; }
/// <summary>
///
/// </summary>
public string? Description { get; set; }
}
/// <summary>
///
/// </summary>
public class PostMediaAttachmentRequestModel : RequestModelBase {
/// <summary>
///
/// </summary>
public string Src { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public MediaTypes MediaType { get; set; } = MediaTypes.Unknown;
/// <summary>
///
/// </summary>
public List<PostMediaAttachmentL10nRequestModel> L10n { get; set; } = new List<PostMediaAttachmentL10nRequestModel>();
}
/// <summary>
///
/// </summary>
public class PostBlogitemL10nRequestModel : RequestModelBase {
/// <summary>
///
/// </summary>
public Locales Locale { get; set; } = Locales.Unknown;
/// <summary>
///
/// </summary>
public string Slug { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string Description { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string Title { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string ShortText { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string Text { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string? PlainText { get; set; }
/// <summary>
///
/// </summary>
public TextFormat TextFormat { get; set; } = TextFormat.Unknown;
/// <summary>
///
/// </summary>
public List<string>? Badges { get; set; }
}
/// <summary>
///
/// </summary>
public class PostBlogItemRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public List<PostBlogitemL10nRequestModel> L10n { get; set; } = new List<PostBlogitemL10nRequestModel>();
/// <summary>
///
/// </summary>
public List<PostMediaAttachmentRequestModel> MediaAttachments { get; set; } = new List<PostMediaAttachmentRequestModel>();
/// <summary>
///
/// </summary>
public List<Guid> Categories { get; set; } = new List<Guid>();
/// <summary>
///
/// </summary>
public List<string>? Tags { get; set; }
/// <summary>
///
/// </summary>
public bool? FamilyFriendly { get; set; }
/// <summary>
///
/// </summary>
public uint? ReadTime { get; set; }
/// <summary>
///
/// </summary>
public uint? Likes { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public BlogDocument ToDomainObject(Guid userId, Guid siteId) => new() {
SiteId = siteId,
L10n = L10n.Select(x => new PostItemL10n() {
Locale = x.Locale,
Slug = x.Slug,
Description = x.Description,
Title = x.Title,
Text = x.Text,
ShortText = x.ShortText,
// TODO: create plain text creation logic
PlainText = "TODO",
TextFormat = x.TextFormat,
Badges = x.Badges
}).ToList(),
MediaAttachments = MediaAttachments.Select(x => new MediaAttachment {
Src = x.Src,
MediaType = x.MediaType,
L10n = x.L10n.Select(y => new MediaAttachmentL10n() {
Locale = y.Locale,
Alt = y.Alt,
Target = y.Target,
Titile = y.Title,
Description = y.Description
}).ToList()
}).ToList(),
Author = userId,
Created = DateTime.UtcNow,
Tags = Tags,
Categories = Categories,
FamilyFriendly = FamilyFriendly,
ReadTime = ReadTime,
Likes = Likes
};
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (L10n.Count == 0)
yield return new ValidationResult($"{nameof(L10n)} {Errors.NullOrEmpty.Name}");
foreach (var item in L10n) {
if (item.Locale == Locales.Unknown)
yield return new ValidationResult($"{nameof(item.Locale)} {Errors.UnableToParse.Name}");
if (string.IsNullOrWhiteSpace(item.Slug))
yield return new ValidationResult($"{nameof(item.Slug)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Description))
yield return new ValidationResult($"{nameof(item.Description)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Title))
yield return new ValidationResult($"{nameof(item.Title)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Text))
yield return new ValidationResult($"{nameof(item.Text)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.ShortText))
yield return new ValidationResult($"{nameof(item.ShortText)} {Errors.NullOrWhiteSpace.Name}");
if (item.TextFormat == TextFormat.Unknown)
yield return new ValidationResult($"{nameof(item.TextFormat)} {Errors.UnableToParse.Name}");
}
if (MediaAttachments.Count == 0)
yield return new ValidationResult($"{nameof(MediaAttachments)} {Errors.NullOrEmpty.Name}");
foreach (var att in MediaAttachments) {
if (string.IsNullOrWhiteSpace(att.Src))
yield return new ValidationResult($"{nameof(att.Src)} {Errors.NullOrWhiteSpace.Name}");
if (att.MediaType == MediaTypes.Unknown)
yield return new ValidationResult($"{nameof(att.MediaType)} {Errors.UnableToParse.Name}");
if (att.L10n.Count == 0)
yield return new ValidationResult($"{nameof(att.L10n)} {Errors.NullOrEmpty.Name}");
foreach (var res in att.L10n) {
if (res.Locale == Locales.Unknown)
yield return new ValidationResult($"{nameof(res.Locale)} {Errors.UnableToParse.Name}");
if (string.IsNullOrWhiteSpace(res.Alt))
yield return new ValidationResult($"{nameof(res.Alt)} {Errors.NullOrWhiteSpace.Name}");
}
}
}
}
}

View File

@ -0,0 +1,257 @@
using System.ComponentModel.DataAnnotations;
using DomainObjects.Documents.Posts;
using DomainObjects.Enumerations;
using DomainObjects.L10n;
using DomainObjects;
using Core.Enumerations;
using Core.Abstractions.Models;
namespace WeatherForecast.Models.Blog.Requests {
/// <summary>
///
/// </summary>
public class PutMediaAttachmentL10nRequestModel {
/// <summary>
///
/// </summary>
public Locales Locale { get; set; } = Locales.Unknown;
/// <summary>
///
/// </summary>
public string Alt { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string? Target { get; set; }
/// <summary>
///
/// </summary>
public string? Title { get; set; }
/// <summary>
///
/// </summary>
public string? Description { get; set; }
}
/// <summary>
///
/// </summary>
public class PutMediaAttachmentRequestModel : RequestModelBase {
/// <summary>
///
/// </summary>
public string Src { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public MediaTypes MediaType { get; set; } = MediaTypes.Unknown;
/// <summary>
///
/// </summary>
public List<PutMediaAttachmentL10nRequestModel> L10n { get; set; } = new List<PutMediaAttachmentL10nRequestModel>();
}
/// <summary>
///
/// </summary>
public class PutBlogitemL10nRequestModel : RequestModelBase {
/// <summary>
///
/// </summary>
public Locales Locale { get; set; } = Locales.Unknown;
/// <summary>
///
/// </summary>
public string Slug { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string Description { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string Title { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string ShortText { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string Text { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string? PlainText { get; set; }
/// <summary>
///
/// </summary>
public TextFormat TextFormat { get; set; } = TextFormat.Unknown;
/// <summary>
///
/// </summary>
public List<string>? Badges { get; set; }
}
/// <summary>
///
/// </summary>
public class PutBlogItemRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public List<PutBlogitemL10nRequestModel> L10n { get; set; } = new List<PutBlogitemL10nRequestModel>();
/// <summary>
///
/// </summary>
public List<PutMediaAttachmentRequestModel> MediaAttachments { get; set; } = new List<PutMediaAttachmentRequestModel>();
/// <summary>
///
/// </summary>
public List<Guid> Categories { get; set; } = new List<Guid>();
/// <summary>
///
/// </summary>
public List<string>? Tags { get; set; }
/// <summary>
///
/// </summary>
public bool? FamilyFriendly { get; set; }
/// <summary>
///
/// </summary>
public uint? ReadTime { get; set; }
/// <summary>
///
/// </summary>
public uint? Likes { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public BlogDocument ToDomainObject(Guid userId, Guid siteId) => new() {
SiteId = siteId,
L10n = L10n.Select(x => new PostItemL10n() {
Locale = x.Locale,
Slug = x.Slug,
Description = x.Description,
Title = x.Title,
Text = x.Text,
ShortText = x.ShortText,
// TODO: create plain text creation logic
PlainText = "TODO",
TextFormat = x.TextFormat,
Badges = x.Badges
}).ToList(),
MediaAttachments = MediaAttachments.Select(x => new MediaAttachment {
Src = x.Src,
MediaType = x.MediaType,
L10n = x.L10n.Select(y => new MediaAttachmentL10n() {
Locale = y.Locale,
Alt = y.Alt,
Target = y.Target,
Titile = y.Title,
Description = y.Description
}).ToList()
}).ToList(),
// Images
Author = userId,
Tags = Tags,
Categories = Categories,
FamilyFriendly = FamilyFriendly,
ReadTime = ReadTime,
Likes = Likes
};
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (L10n.Count == 0)
yield return new ValidationResult($"{nameof(L10n)} {Errors.NullOrEmpty}");
foreach (var item in L10n) {
if (item.Locale == Locales.Unknown)
yield return new ValidationResult($"{nameof(item.Locale)} {Errors.UnableToParse.Name}");
if (string.IsNullOrWhiteSpace(item.Slug))
yield return new ValidationResult($"{nameof(item.Slug)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Description))
yield return new ValidationResult($"{nameof(item.Description)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Title))
yield return new ValidationResult($"{nameof(item.Title)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Text))
yield return new ValidationResult($"{nameof(item.Text)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.ShortText))
yield return new ValidationResult($"{nameof(item.ShortText)} {Errors.NullOrWhiteSpace.Name}");
if (item.TextFormat == TextFormat.Unknown)
yield return new ValidationResult($"{nameof(item.TextFormat)} {Errors.UnableToParse.Name}");
}
if (MediaAttachments.Count == 0)
yield return new ValidationResult($"{nameof(MediaAttachments)} {Errors.NullOrEmpty.Name}");
foreach (var att in MediaAttachments) {
if (string.IsNullOrWhiteSpace(att.Src))
yield return new ValidationResult($"{nameof(att.Src)} {Errors.NullOrWhiteSpace.Name}");
if (att.MediaType == MediaTypes.Unknown)
yield return new ValidationResult($"{nameof(att.MediaType)} {Errors.UnableToParse.Name}");
if (att.L10n.Count == 0)
yield return new ValidationResult($"{nameof(att.L10n)} {Errors.NullOrEmpty.Name}");
foreach (var res in att.L10n) {
if (res.Locale == Locales.Unknown)
yield return new ValidationResult($"{nameof(res.Locale)} {Errors.UnableToParse.Name}");
if (string.IsNullOrWhiteSpace(res.Alt))
yield return new ValidationResult($"{nameof(res.Alt)} {Errors.NullOrWhiteSpace.Name}");
}
}
}
}
}

View File

@ -9,7 +9,7 @@ namespace WeatherForecast.Models.Blog.Responses
/// <summary>
///
/// </summary>
public class BlogItemResponseModel : PostItemResponseModelBase<BlogDocument> {
public class GetBlogItemResponseModel : PostItemResponseModelBase<BlogDocument> {
/// <summary>
///
@ -26,7 +26,7 @@ namespace WeatherForecast.Models.Blog.Responses
/// </summary>
/// <param name="blogItem"></param>
/// <param name="categories"></param>
public BlogItemResponseModel(BlogDocument blogItem, List<DomainObjects.Documents.Categories.Category> categories) : base(blogItem, categories) {
public GetBlogItemResponseModel(BlogDocument blogItem, List<DomainObjects.Documents.Categories.Category> categories) : base(blogItem, categories) {
ReadTime = blogItem.ReadTime;
Likes = blogItem.Likes;
}
@ -37,7 +37,7 @@ namespace WeatherForecast.Models.Blog.Responses
/// <param name="blogItem"></param>
/// <param name="categories"></param>
/// <param name="locale"></param>
public BlogItemResponseModel(BlogDocument blogItem, List<DomainObjects.Documents.Categories.Category> categories, Locales locale) : base(blogItem, categories, locale) {
public GetBlogItemResponseModel(BlogDocument blogItem, List<DomainObjects.Documents.Categories.Category> categories, Locales locale) : base(blogItem, categories, locale) {
ReadTime = blogItem.ReadTime;
Likes = blogItem.Likes;
}

View File

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

View File

@ -12,7 +12,7 @@ namespace WeatherForecast.Models.Category.Requests
/// <summary>
///
/// </summary>
public class CategoryL10nModel : RequestModelBase<CategoryL10n> {
public class CategoryL10nModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -49,7 +49,7 @@ namespace WeatherForecast.Models.Category.Requests
/// <param name="validationContext"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Locale))
yield return new ValidationResult($"{nameof(Locale)} {Errors.NullOrWhiteSpace.Name}");
else if (Enumeration.FromDisplayName<Locales>(Locale) == null)

View File

@ -0,0 +1,28 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.CategoryItem.Requests {
/// <summary>
///
/// </summary>
public class GetCategoryItemSlugRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public string Slug { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Slug))
yield return new ValidationResult($"{Errors.NullOrWhiteSpace} {nameof(Slug)}");
}
}
}

View File

@ -0,0 +1,29 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Enumerations;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.CategoryItem.Requests {
/// <summary>
///
/// </summary>
public class GetCategoryItemsRequestModel : RequestModelBase {
/// <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

@ -10,7 +10,7 @@ namespace WeatherForecast.Models.Category.Requests
/// <summary>
///
/// </summary>
public class CategoryItemRequestModel : RequestModelBase<DomainObjects.Documents.Categories.Category> {
public class PostCategoryItemRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -33,7 +33,7 @@ namespace WeatherForecast.Models.Category.Requests
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (L10n.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(L10n)} ${Errors.NullOrEmpty}");
}

View File

@ -0,0 +1,41 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using Extensions;
using System.ComponentModel.DataAnnotations;
using DomainObjects.Documents.Categories;
namespace WeatherForecast.Models.Category.Requests
{
/// <summary>
///
/// </summary>
public class PutCategoryItemRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public List<CategoryL10nModel>? L10n { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public DomainObjects.Documents.Categories.Category ToDomainObject(Guid siteId) => new DomainObjects.Documents.Categories.Category() {
SiteId = siteId,
L10n = L10n.Select(x => x.ToDomainObject()).ToList()
};
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (L10n.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(L10n)} ${Errors.NullOrEmpty}");
}
}
}

View File

@ -8,7 +8,7 @@ namespace WeatherForecast.Models.Category.Responses
/// <summary>
///
/// </summary>
public class CategoryItemResponseModel : ResponseModelBase {
public class GetCategoryItemResponseModel : ResponseModelBase {
/// <summary>
///
@ -39,7 +39,7 @@ namespace WeatherForecast.Models.Category.Responses
///
/// </summary>
/// <param name="category"></param>
public CategoryItemResponseModel(DomainObjects.Documents.Categories.Category category) {
public GetCategoryItemResponseModel(DomainObjects.Documents.Categories.Category category) {
Id = category.Id;
SiteId = category.SiteId;
@ -51,7 +51,7 @@ namespace WeatherForecast.Models.Category.Responses
/// </summary>
/// <param name="category"></param>
/// <param name="locale"></param>
public CategoryItemResponseModel(DomainObjects.Documents.Categories.Category category, Locales locale) {
public GetCategoryItemResponseModel(DomainObjects.Documents.Categories.Category category, Locales locale) {
Id = category.Id;
SiteId = category.SiteId;

View File

@ -0,0 +1,29 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Enumerations;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.Content.Requests {
/// <summary>
///
/// </summary>
public class GetContentRequestModel : 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

@ -7,7 +7,7 @@ namespace WeatherForecast.Models.Content.Responses {
/// <summary>
///
/// </summary>
public class ContentResponseModel : ResponseModelBase {
public class GetContentResponseModel : ResponseModelBase {
/// <summary>
///
@ -103,7 +103,7 @@ namespace WeatherForecast.Models.Content.Responses {
///
/// </summary>
/// <param name="domainObject"></param>
public ContentResponseModel(ContentDocument domainObject) {
public GetContentResponseModel(ContentDocument domainObject) {
SiteName = domainObject.SiteName;
SiteUrl = domainObject.SiteUrl;

View File

@ -1,11 +1,11 @@
using Core.Abstractions.Models;
namespace WeatherForecast.Models.File.Responses {
namespace WeatherForecast.Models.Images.Responses {
/// <summary>
///
/// </summary>
public class FileResponseModel : ResponseModelBase {
public class GetImageResponseModel : ResponseModelBase {
/// <summary>
/// File name

View File

@ -9,7 +9,7 @@ namespace WeatherForecast.Models.Initialization.Requests {
/// <summary>
///
/// </summary>
public class InitializeSystemRequestModel : RequestModelBase<InitializeSystemRequestModel> {
public class PostInitializeSystemRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -49,7 +49,7 @@ namespace WeatherForecast.Models.Initialization.Requests {
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public InitializeSystemRequestModel ToDomainObject() {
public PostInitializeSystemRequestModel ToDomainObject() {
throw new NotImplementedException();
}
@ -58,7 +58,7 @@ namespace WeatherForecast.Models.Initialization.Requests {
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(SiteName))
yield return new ValidationResult($"{nameof(SiteName)} ${Errors.NullOrEmpty}");

View File

@ -0,0 +1,47 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Enumerations;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.Shop.Requests {
/// <summary>
///
/// </summary>
public class GetShopItemsRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public Guid? Category { get; set; }
/// <summary>
///
/// </summary>
public string? SearchText { get; set; }
/// <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 (Locale == Locales.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse} {nameof(Locale)}");
}
}
}

View File

@ -0,0 +1,282 @@
using System.ComponentModel.DataAnnotations;
using DomainObjects.Documents.Posts;
using DomainObjects.Enumerations;
using DomainObjects.L10n;
using DomainObjects;
using Core.Enumerations;
using Core.Abstractions.Models;
namespace WeatherForecast.Models.Requests {
/// <summary>
///
/// </summary>
public class PostMediaAttachmentL10nRequestModel : RequestModelBase {
/// <summary>
///
/// </summary>
public Locales Locale { get; set; } = Locales.Unknown;
/// <summary>
///
/// </summary>
public string Alt { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string? Target { get; set; }
/// <summary>
///
/// </summary>
public string? Title { get; set; }
/// <summary>
///
/// </summary>
public string? Description { get; set; }
}
/// <summary>
///
/// </summary>
public class PostMediaAttachmentRequestModel : RequestModelBase {
/// <summary>
///
/// </summary>
public string Src { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public MediaTypes MediaType { get; set; } = MediaTypes.Unknown;
/// <summary>
///
/// </summary>
public List<PostMediaAttachmentL10nRequestModel> L10n { get; set; } = new List<PostMediaAttachmentL10nRequestModel>();
}
/// <summary>
///
/// </summary>
public class PostShopItemL10nRequestModel {
/// <summary>
///
/// </summary>
public Locales Locale { get; set; } = Locales.Unknown;
/// <summary>
///
/// </summary>
public string Slug { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string Description { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string Title { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string ShortText { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string Text { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string? PlainText { get; set; }
/// <summary>
///
/// </summary>
public TextFormat TextFormat { get; set; } = TextFormat.Unknown;
/// <summary>
///
/// </summary>
public List<string>? Badges { get; set; }
}
/// <summary>
///
/// </summary>
public class PostShopItemRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public List<PostShopItemL10nRequestModel> L10n { get; set; } = new List<PostShopItemL10nRequestModel>();
/// <summary>
///
/// </summary>
public List<PostMediaAttachmentRequestModel> MediaAttachments { get; set; } = new List<PostMediaAttachmentRequestModel>();
/// <summary>
///
/// </summary>
public List<Guid> Categories { get; set; } = new List<Guid>();
/// <summary>
///
/// </summary>
public List<string>? Tags { get; set; }
/// <summary>
///
/// </summary>
public bool? FamilyFriendly { get; set; }
/// <summary>
///
/// </summary>
public string BrandName { get; set; } = string.Empty;
/// <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>
/// <returns></returns>
public ShopDocument ToDomainObject(string sku, Guid userId, Guid siteId) => new ShopDocument() {
Sku = sku,
SiteId = siteId,
L10n = L10n.Select(x => new PostItemL10n() {
Locale = x.Locale,
Slug = x.Slug,
Description = x.Description,
Title = x.Title,
Text = x.Text,
ShortText = x.ShortText,
// TODO: create plain text creation logic
PlainText = "TODO",
TextFormat = x.TextFormat,
Badges = x.Badges
}).ToList(),
MediaAttachments = MediaAttachments.Select(x => new MediaAttachment {
Src = x.Src,
MediaType = x.MediaType,
L10n = x.L10n.Select(y => new MediaAttachmentL10n() {
Locale = y.Locale,
Alt = y.Alt,
Target = y.Target,
Titile = y.Title,
Description = y.Description
}).ToList()
}).ToList(),
Author = userId,
Created = DateTime.UtcNow,
Tags = Tags,
FamilyFriendly = FamilyFriendly,
BrandName = BrandName,
Rating = Rating,
Price = Price,
NewPrice = NewPrice,
Quantity = Quantity
};
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (L10n.Count == 0)
yield return new ValidationResult($"{nameof(L10n)} {Errors.NullOrEmpty.Name}");
foreach (var item in L10n) {
if (item.Locale == Locales.Unknown)
yield return new ValidationResult($"{nameof(item.Locale)} {Errors.UnableToParse.Name}");
if (string.IsNullOrWhiteSpace(item.Slug))
yield return new ValidationResult($"{nameof(item.Slug)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Description))
yield return new ValidationResult($"{nameof(item.Description)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Title))
yield return new ValidationResult($"{nameof(item.Title)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Text))
yield return new ValidationResult($"{nameof(item.Text)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.ShortText))
yield return new ValidationResult($"{nameof(item.ShortText)} {Errors.NullOrWhiteSpace.Name}");
if (item.TextFormat == TextFormat.Unknown)
yield return new ValidationResult($"{nameof(item.TextFormat)} {Errors.UnableToParse.Name}");
}
if (MediaAttachments.Count == 0)
yield return new ValidationResult($"{nameof(MediaAttachments)} {Errors.NullOrEmpty.Name}");
foreach (var att in MediaAttachments) {
if (string.IsNullOrWhiteSpace(att.Src))
yield return new ValidationResult($"{nameof(att.Src)} {Errors.NullOrWhiteSpace.Name}");
if (att.MediaType == MediaTypes.Unknown)
yield return new ValidationResult($"{nameof(att.MediaType)} {Errors.UnableToParse.Name}");
if (att.L10n.Count == 0)
yield return new ValidationResult($"{nameof(att.L10n)} {Errors.NullOrEmpty.Name}");
foreach (var res in att.L10n) {
if (res.Locale == Locales.Unknown)
yield return new ValidationResult($"{nameof(res.Locale)} {Errors.UnableToParse.Name}");
if (string.IsNullOrWhiteSpace(res.Alt))
yield return new ValidationResult($"{nameof(res.Alt)} {Errors.NullOrWhiteSpace.Name}");
}
}
if (string.IsNullOrWhiteSpace(BrandName))
yield return new ValidationResult($"{nameof(BrandName)} {Errors.NullOrWhiteSpace}");
if (Price == 0)
yield return new ValidationResult($"{nameof(Price)} {Errors.NullOrEmpty.Name}");
if (Quantity == 0)
yield return new ValidationResult($"{nameof(Quantity)} {Errors.NullOrEmpty}");
}
}
}

View File

@ -0,0 +1,316 @@
using System.ComponentModel.DataAnnotations;
using Core.Enumerations;
using Extensions;
using DomainObjects.Documents.Posts;
using Core.Abstractions.Models;
using Core.Abstractions;
using DomainObjects.Enumerations;
using DomainObjects.L10n;
using DomainObjects;
namespace WeatherForecast.Models.Requests {
/// <summary>
///
/// </summary>
public class PutMediaAttachmentL10nRequestModel {
/// <summary>
///
/// </summary>
public string? Locale { 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>
/// <returns></returns>
public MediaAttachmentL10n ToDomainObject() {
return new MediaAttachmentL10n() {
Locale = Enumeration.FromDisplayName<Locales>(Locale),
Alt = Alt
};
}
}
/// <summary>
///
/// </summary>
public class PutMediaAttachmentRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public string? Src { get; set; }
/// <summary>
///
/// </summary>
public string? MediaType { get; set; }
/// <summary>
///
/// </summary>
public List<PutMediaAttachmentL10nRequestModel>? L10n { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public MediaAttachment ToDomainObject() {
return new MediaAttachment {
Src = Src,
MediaType = Enumeration.FromDisplayName<MediaTypes>(MediaType),
L10n = L10n.Select(x => x.ToDomainObject()).ToList()
};
}
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Src))
yield return new ValidationResult($"{nameof(Src)} {Errors.NullOrWhiteSpace}");
if (string.IsNullOrWhiteSpace(MediaType))
yield return new ValidationResult($"{nameof(MediaType)} {Errors.NullOrWhiteSpace}");
if (L10n.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(L10n)} {Errors.NullOrEmpty}");
else {
foreach (var res in L10n) {
if (string.IsNullOrWhiteSpace(res.Locale))
yield return new ValidationResult($"{nameof(res.Locale)} {Errors.NullOrWhiteSpace.Name}");
else if (Enumeration.FromDisplayName<Locales>(res.Locale) == null)
yield return new ValidationResult($"{nameof(res.Locale)} {Errors.WrongOrNotManaged}");
if (string.IsNullOrWhiteSpace(res.Alt))
yield return new ValidationResult($"{nameof(res.Alt)} {Errors.NullOrWhiteSpace.Name}");
}
}
}
}
public class PutShopItemL10nRequestModel {
/// <summary>
///
/// </summary>
public string? Locale { 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 string? TextFormat { get; set; }
/// <summary>
///
/// </summary>
public List<string>? Badges { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public PostItemL10n ToDomainObject() {
return new PostItemL10n() {
Locale = Enumeration.FromDisplayName<Locales>(Locale),
Slug = Slug,
Description = Description,
Title = Title,
Text = Text,
ShortText = ShortText,
// TODO: create plain text creation logic
PlainText = "TODO",
TextFormat = Enumeration.FromDisplayName<TextFormat>(TextFormat),
Badges = Badges
};
}
}
/// <summary>
///
/// </summary>
public class PutShopItemRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
public List<PutShopItemL10nRequestModel>? L10n { get; set; }
/// <summary>
///
/// </summary>
public List<PutMediaAttachmentRequestModel>? MediaAttachments { get; set; }
/// <summary>
///
/// </summary>
public List<Guid>? Categories { get; set; }
/// <summary>
///
/// </summary>
public List<string>? Tags { get; set; }
/// <summary>
///
/// </summary>
public bool? FamilyFriendly { get; set; }
/// <summary>
///
/// </summary>
public string? BrandName { 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>
/// <returns></returns>
public ShopDocument ToDomainObject(string sku, Guid userId, Guid siteId) => new ShopDocument() {
Sku = sku,
SiteId = siteId,
L10n = L10n.Select(x => x.ToDomainObject()).ToList(),
MediaAttachments = MediaAttachments?.Select(x => x.ToDomainObject()).ToList(),
Author = userId,
Created = DateTime.UtcNow,
Tags = Tags,
FamilyFriendly = FamilyFriendly,
BrandName = BrandName,
Rating = Rating,
Price = Price.Value,
NewPrice = NewPrice,
Quantity = Quantity.Value
};
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (L10n.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(L10n)} {Errors.NullOrEmpty}");
else {
foreach (var item in L10n) {
if (string.IsNullOrWhiteSpace(item.Locale))
yield return new ValidationResult($"{nameof(item.Locale)} {Errors.NullOrWhiteSpace.Name}");
else if (Enumeration.FromDisplayName<Locales>(item.Locale) == null)
yield return new ValidationResult($"{nameof(item.Locale)} {Errors.WrongOrNotManaged}");
if (string.IsNullOrWhiteSpace(item.Slug))
yield return new ValidationResult($"{nameof(item.Slug)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Description))
yield return new ValidationResult($"{nameof(item.Description)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Title))
yield return new ValidationResult($"{nameof(item.Title)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.Text))
yield return new ValidationResult($"{nameof(item.Text)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.ShortText))
yield return new ValidationResult($"{nameof(item.ShortText)} {Errors.NullOrWhiteSpace.Name}");
if (string.IsNullOrWhiteSpace(item.TextFormat))
yield return new ValidationResult($"{nameof(item.TextFormat)} {Errors.NullOrWhiteSpace.Name}");
else if (Enumeration.FromDisplayName<TextFormat>(item.TextFormat) == null)
yield return new ValidationResult($"{nameof(item.TextFormat)} {Errors.WrongOrNotManaged}");
}
}
if (MediaAttachments.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(MediaAttachments)} {Errors.NullOrEmpty}");
if (string.IsNullOrWhiteSpace(BrandName))
yield return new ValidationResult($"{nameof(BrandName)} {Errors.NullOrWhiteSpace}");
if (Price == null || (Price != null && Price == 0))
yield return new ValidationResult($"{nameof(Price)} {Errors.NullOrEmpty.Name}");
if (Quantity == null || (Quantity != null && Quantity == 0))
yield return new ValidationResult($"{nameof(Quantity)} {Errors.NullOrEmpty}");
}
}
}

View File

@ -1,46 +0,0 @@
using System.ComponentModel.DataAnnotations;
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Documents;
namespace WeatherForecast.Models.Shop.Requests {
/// <summary>
///
/// </summary>
public class ShopCartItemRequestModel : RequestModelBase<ShopCartDocument> {
/// <summary>
///
/// </summary>
public uint? Quantity { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public ShopCartDocument ToDomainObject(string sku, Guid userId, Guid 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 override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (Quantity == null || (Quantity != null && Quantity == 0))
yield return new ValidationResult($"{nameof(Quantity)} {Errors.NullOrEmpty}");
}
}
}

View File

@ -1,85 +0,0 @@
using System.ComponentModel.DataAnnotations;
using Core.Enumerations;
using Extensions;
using WeatherForecast.Models.Abstractions.PostItem.Requests;
using DomainObjects.Documents.Posts;
namespace WeatherForecast.Models.Requests
{
/// <summary>
///
/// </summary>
public class ShopItemRequestModel : PostItemRequestModelBase<ShopDocument> {
/// <summary>
///
/// </summary>
public string? BrandName { 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>
/// <returns></returns>
public ShopDocument ToDomainObject(string sku, Guid userId, Guid siteId) => new ShopDocument() {
Sku = sku,
SiteId = siteId,
L10n = L10n.Select(x => x.ToDomainObject()).ToList(),
MediaAttachments = MediaAttachments?.Select(x => x.ToDomainObject()).ToList(),
Author = userId,
Created = DateTime.UtcNow,
Tags = Tags,
FamilyFriendly = FamilyFriendly,
BrandName = BrandName,
Rating = Rating,
Price = Price.Value,
NewPrice = NewPrice,
Quantity = Quantity.Value
};
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (L10n.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(L10n)} {Errors.NullOrEmpty}");
if (MediaAttachments.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(MediaAttachments)} {Errors.NullOrEmpty}");
if (string.IsNullOrWhiteSpace(BrandName))
yield return new ValidationResult($"{nameof(BrandName)} {Errors.NullOrWhiteSpace}");
if (Price == null || (Price != null && Price == 0))
yield return new ValidationResult($"{nameof(Price)} {Errors.NullOrEmpty.Name}");
if (Quantity == null || (Quantity != null && Quantity == 0))
yield return new ValidationResult($"{nameof(Quantity)} {Errors.NullOrEmpty}");
}
}
}

View File

@ -9,7 +9,7 @@ namespace WeatherForecast.Models.Shop.Responses
/// <summary>
///
/// </summary>
public class ShopItemResponseModel : PostItemResponseModelBase<ShopDocument> {
public class GetShopItemResponseModel : PostItemResponseModelBase<ShopDocument> {
/// <summary>
///
@ -41,7 +41,7 @@ namespace WeatherForecast.Models.Shop.Responses
/// </summary>
/// <param name="shopCatalogItem"></param>
/// <param name="categories"></param>
public ShopItemResponseModel(ShopDocument shopCatalogItem, List<DomainObjects.Documents.Categories.Category> categories) : base(shopCatalogItem, categories) {
public GetShopItemResponseModel(ShopDocument shopCatalogItem, List<DomainObjects.Documents.Categories.Category> categories) : base(shopCatalogItem, categories) {
Sku = shopCatalogItem.Sku;
Rating = shopCatalogItem.Rating;
Price = shopCatalogItem.Price;
@ -55,7 +55,7 @@ namespace WeatherForecast.Models.Shop.Responses
/// <param name="shopCatalogItem"></param>
/// <param name="categories"></param>
/// <param name="locale"></param>
public ShopItemResponseModel(ShopDocument shopCatalogItem, List<DomainObjects.Documents.Categories.Category> categories, Locales locale) : base(shopCatalogItem, categories, locale) {
public GetShopItemResponseModel(ShopDocument shopCatalogItem, List<DomainObjects.Documents.Categories.Category> categories, Locales locale) : base(shopCatalogItem, categories, locale) {
Sku = shopCatalogItem.Sku;
Rating = shopCatalogItem.Rating;
Price = shopCatalogItem.Price;

View File

@ -5,7 +5,7 @@ namespace WeatherForecast.Models.Shop.Responses {
/// <summary>
///
/// </summary>
public class ShopItemsResponseModel : PaginationModelBase<ShopItemResponseModel> {
public class GetShopItemsResponseModel : PaginationModelBase<GetShopItemResponseModel> {
/// <summary>
///
@ -13,7 +13,7 @@ namespace WeatherForecast.Models.Shop.Responses {
/// <param name="currentPage"></param>
/// <param name="totalPages"></param>
/// <param name="items"></param>
public ShopItemsResponseModel(int currentPage, int totalPages, List<ShopItemResponseModel> items)
public GetShopItemsResponseModel(int currentPage, int totalPages, List<GetShopItemResponseModel> items)
: base(currentPage, totalPages, items) { }
}
}

View File

@ -1,93 +0,0 @@
using Core.Abstractions.Models;
using DomainObjects.Documents;
using DomainObjects.Documents.Posts;
using DomainObjects.Enumerations;
using WeatherForecast.Models.Abstractions.PostItem.Responses;
namespace WeatherForecast.Models.Responses
{
/// <summary>
///
/// </summary>
public class ShopCartItemResponseModel : ResponseModelBase {
/// <summary>
///
/// </summary>
public string Slug { get; set; }
/// <summary>
///
/// </summary>
public string Sku { get; set; }
/// <summary>
///
/// </summary>
public MediaAttachmentResponseModel? 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 ShopCartItemResponseModel(ShopDocument shopItem, ShopCartDocument shopCartItem, Locales locale) {
Sku = shopItem.Sku;
BrandName = shopItem.BrandName;
Created = shopItem.Created;
Price = shopItem.Price;
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;
}
if(shopItem.MediaAttachments != null)
Image = new MediaAttachmentResponseModel(shopItem.MediaAttachments.First(), locale);
}
}
}

View File

@ -0,0 +1,32 @@
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Enumerations;
using System.ComponentModel.DataAnnotations;
namespace WeatherForecast.Models.ShopCart.Requests
{
/// <summary>
///
/// </summary>
public class GetShopCartItemRequestModel : 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,32 @@
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,51 @@
using System.ComponentModel.DataAnnotations;
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Documents;
namespace WeatherForecast.Models.ShopCart.Requests
{
/// <summary>
///
/// </summary>
public class PostShopCartItemRequestModel : RequestModelBase, IValidatableObject
{
/// <summary>
///
/// </summary>
public uint? Quantity { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public ShopCartDocument ToDomainObject(string sku, Guid userId, Guid 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}");
}
}
}

View File

@ -0,0 +1,51 @@
using System.ComponentModel.DataAnnotations;
using Core.Abstractions.Models;
using Core.Enumerations;
using DomainObjects.Documents;
namespace WeatherForecast.Models.ShopCart.Requests
{
/// <summary>
///
/// </summary>
public class PutShopCartItemRequestModel : RequestModelBase, IValidatableObject
{
/// <summary>
///
/// </summary>
public uint? Quantity { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public ShopCartDocument ToDomainObject(string sku, Guid userId, Guid 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}");
}
}
}

View File

@ -0,0 +1,96 @@
using Core.Abstractions.Models;
using DomainObjects.Documents;
using DomainObjects.Documents.Posts;
using DomainObjects.Enumerations;
using WeatherForecast.Models.Abstractions.PostItem.Responses;
namespace WeatherForecast.Models.ShopCart.Responses
{
/// <summary>
///
/// </summary>
public class GetShopCartItemResponseModel : ResponseModelBase
{
/// <summary>
///
/// </summary>
public string Slug { get; set; }
/// <summary>
///
/// </summary>
public string Sku { get; set; }
/// <summary>
///
/// </summary>
public MediaAttachmentResponseModel? 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 GetShopCartItemResponseModel(ShopDocument shopItem, ShopCartDocument shopCartItem, Locales locale)
{
Sku = shopItem.Sku;
BrandName = shopItem.BrandName;
Created = shopItem.Created;
Price = shopItem.Price;
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;
}
if (shopItem.MediaAttachments != null)
Image = new MediaAttachmentResponseModel(shopItem.MediaAttachments.First(), locale);
}
}
}

View File

@ -10,7 +10,7 @@ namespace WeatherForecast.Models.Template.Requests {
/// <summary>
///
/// </summary>
public class PostTemplateRequestModel : RequestModelBase {
public class PostTemplateRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
@ -24,7 +24,7 @@ namespace WeatherForecast.Models.Template.Requests {
/// <param name="validationContext"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (TemplateType == TemplateTypes.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse.Name} {nameof(TemplateType)}");

View File

@ -0,0 +1,31 @@
using Core.Abstractions.Models;
using Core.Converters;
using Core.Enumerations;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
namespace WeatherForecast.Models.Template.Requests {
/// <summary>
///
/// </summary>
public class PutTemplateRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
///
/// </summary>
[JsonConverter(typeof(EnumerationDisplayNameConverter<TemplateTypes>))]
public TemplateTypes TemplateType { get; set; } = TemplateTypes.Unknown;
/// <summary>
///
/// </summary>
/// <param name="validationContext"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (TemplateType == TemplateTypes.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse.Name} {nameof(TemplateType)}");
}
}
}

View File

@ -8,7 +8,7 @@ namespace WeatherForecast.Models.Utils.Requests {
/// <summary>
///
/// </summary>
public class EncryptStringAesRequestModel : RequestModelBase {
public class PostEncryptStringAesRequestModel : RequestModelBase, IValidatableObject {
/// <summary>
/// String to encrypt
@ -31,7 +31,7 @@ namespace WeatherForecast.Models.Utils.Requests {
/// <param name="validationContext"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrEmpty(InputString))
yield return new ValidationResult($"{nameof(InputString)} {Errors.NullOrEmpty}");

View File

@ -5,7 +5,7 @@ namespace WeatherForecast.Models.WeatherForecast.Responses {
/// <summary>
///
/// </summary>
public class WeatherForecastResponseModel : ResponseModelBase {
public class GetWeatherForecastResponseModel : ResponseModelBase {
/// <summary>
///

View File

@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Authorization;
using Core.Enumerations;
using DataProviders.Collections;
@ -44,32 +43,17 @@ public class BlogAuthorizationHandler : AuthorizationHandlerBase<BlogAuthorizati
var userRole = GetRole(site, user);
// Can only Admin, Editor, Author, Contributor (cannot set publish date)
if (requirement.Action == CrudActions.Create
&& (userRole != Roles.Admin
&& userRole != Roles.Editor
&& userRole != Roles.Author
&& userRole != Roles.Contributor
&& (userRole == Roles.Contributor && resource.Any(x => x.Published != null))))
var req = requirement.Roles.SingleOrDefault(x => x.Role == userRole);
if (req == null)
return Task.CompletedTask;
// Can only Admin, Editor, Author, Contributor
if (requirement.Action == CrudActions.Read
&& (userRole != Roles.Admin
&& userRole != Roles.Editor
&& userRole != Roles.Author
&& userRole != Roles.Contributor))
return Task.CompletedTask;
foreach (var res in resource) {
if (req.OwnOnly && res.Author != user.Id)
return Task.CompletedTask;
// Can only Admin, Editor, Author (own), Contributor (own, not yet pubblished)
if ((requirement.Action == CrudActions.Update || requirement.Action == CrudActions.Delete)
&& (userRole != Roles.Admin
&& userRole != Roles.Editor
&& userRole != Roles.Author
&& userRole != Roles.Contributor
&& ((userRole == Roles.Author || userRole == Roles.Contributor) && resource.Any(x => x.Author != user.Id))
&& (userRole == Roles.Contributor && resource.Any(x => x.Published != null))))
return Task.CompletedTask;
if (req.DenyPublished && res.Published != null)
return Task.CompletedTask;
}
context.Succeed(requirement);
@ -80,5 +64,28 @@ public class BlogAuthorizationHandler : AuthorizationHandlerBase<BlogAuthorizati
/// <summary>
///
/// </summary>
public class BlogAuthorizationRequirement : AuthorizationRequirementBase { }
public class BlogRole {
/// <summary>
///
/// </summary>
public Roles Role { get; init; }
/// <summary>
///
/// </summary>
public bool DenyPublished { get; init; } = false;
/// <summary>
///
/// </summary>
public bool OwnOnly { get; init; } = false;
}
/// <summary>
///
/// </summary>
public class BlogAuthorizationRequirement : AuthorizationRequirementBase {
public List<BlogRole> Roles { get; init; }
}

View File

@ -41,25 +41,8 @@ public class CategoryAuthorizationHandler : AuthorizationHandlerBase<CategoryAut
var userRole = GetRole(site, user);
// Can Admin, Editor, Shop manager
if ((requirement.Action == CrudActions.Create || requirement.Action == CrudActions.Update)
&& (userRole != Roles.Admin
&& userRole != Roles.Editor
&& userRole != Roles.ShopManager))
return Task.CompletedTask;
// Can Admin, Editor, Author, Contributor, Shop manager
if (requirement.Action == CrudActions.Read
&& (userRole != Roles.Admin
&& userRole != Roles.Editor
&& userRole != Roles.Author
&& userRole != Roles.Contributor
&& userRole != Roles.ShopManager))
return Task.CompletedTask;
// Can Admin only
if (requirement.Action == CrudActions.Delete
&& userRole != Roles.Admin)
var req = requirement.Roles.SingleOrDefault(x => x.Role == userRole);
if (req == null)
return Task.CompletedTask;
context.Succeed(requirement);
@ -71,4 +54,14 @@ public class CategoryAuthorizationHandler : AuthorizationHandlerBase<CategoryAut
/// <summary>
///
/// </summary>
public class CategoryAuthorizationRequirement : AuthorizationRequirementBase { }
public class CategoryRole {
public Roles Role { get; init; }
}
/// <summary>
///
/// </summary>
public class CategoryAuthorizationRequirement : AuthorizationRequirementBase {
public List<CategoryRole> Roles { get; init; }
}

View File

@ -0,0 +1,89 @@
using DataProviders.Buckets;
using DataProviders.Collections;
using DomainObjects.Documents.Users;
using FileSecurityService;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using WeatherForecast.Policies.Abstractions;
namespace WeatherForecast.Policies {
/// <summary>
///
/// </summary>
public class DkimAuthorizationHandler : AuthorizationHandlerBase<DkimAuthorisationRequirement, List<BucketFile>> {
private readonly IFileSecurityService _fileSecurityService;
/// <summary>
///
/// </summary>
/// <param name="configuration"></param>
/// <param name="contextAccessor"></param>
/// <param name="siteDataProvider"></param>
/// <param name="userDataProvider"></param>
/// <param name="fileSecurityService"></param>
public DkimAuthorizationHandler(
IOptions<Configuration> configuration,
IHttpContextAccessor contextAccessor,
ISiteDataProvider siteDataProvider,
IUserDataProvider userDataProvider,
IFileSecurityService fileSecurityService
) : base(configuration, contextAccessor, siteDataProvider, userDataProvider) {
_fileSecurityService = fileSecurityService;
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="requirement"></param>
/// <param name="resource"></param>
/// <returns></returns>
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DkimAuthorisationRequirement requirement, List<BucketFile> resource) {
var (site, user) = GetUser(context);
if (site == null || user == null)
return Task.CompletedTask;
var userRole = GetRole(site, user);
var req = requirement.Roles.SingleOrDefault(x => x.Role == userRole);
if (req == null)
return Task.CompletedTask;
foreach (var res in resource) {
var (fileCategory, signatureResult) = _fileSecurityService.CheckFileSignature(res.Name, res.Bytes, res.ContentType);
if (!signatureResult.IsSuccess || fileCategory == null)
return Task.CompletedTask;
}
context.Succeed(requirement);
return Task.CompletedTask;
}
}
/// <summary>
///
/// </summary>
public class DkimRole {
/// <summary>
///
/// </summary>
public Roles Role { get; init; }
}
/// <summary>
///
/// </summary>
public class DkimAuthorisationRequirement : AuthorizationRequirementBase {
/// <summary>
///
/// </summary>
public List<DkimRole> Roles { get; init; }
}
}

View File

@ -1,101 +0,0 @@
using Core.Enumerations;
using DataProviders.Buckets;
using DataProviders.Collections;
using DomainObjects.Documents.Users;
using FileSecurityService;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using WeatherForecast.Policies.Abstractions;
namespace WeatherForecast.Policies;
/// <summary>
///
/// </summary>
public class FileAuthorisationHandler : AuthorizationHandlerBase<FileAuthorisationRequirement, List<BucketFile>> {
private readonly IFileSecurityService _fileSecurityService;
/// <summary>
///
/// </summary>
/// <param name="configuration"></param>
/// <param name="contextAccessor"></param>
/// <param name="siteDataProvider"></param>
/// <param name="userDataProvider"></param>
/// <param name="fileSecurityService"></param>
public FileAuthorisationHandler(
IOptions<Configuration> configuration,
IHttpContextAccessor contextAccessor,
ISiteDataProvider siteDataProvider,
IUserDataProvider userDataProvider,
IFileSecurityService fileSecurityService
) : base(configuration, contextAccessor, siteDataProvider, userDataProvider) {
_fileSecurityService = fileSecurityService;
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="requirement"></param>
/// <param name="resource"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FileAuthorisationRequirement requirement, List<BucketFile> resource) {
var (site, user) = GetUser(context);
if (site == null || user == null)
return Task.CompletedTask;
var userRole = GetRole(site, user);
if (resource.Any(x => {
var (fileCategory, signatureResult) = _fileSecurityService.CheckFileSignature(x.Name, x.Bytes, x.ContentType);
return !signatureResult.IsSuccess || fileCategory == null;
}))
return Task.CompletedTask;
// Can Admin, Editor, Author, Contributor, Shop manager
if (requirement.Action == CrudActions.Create
&& userRole != Roles.Admin
&& userRole != Roles.Editor
&& userRole != Roles.Author
&& userRole != Roles.Contributor
&& userRole != Roles.ShopManager)
return Task.CompletedTask;
// Can Admin, Editor, Author (own), Contributor (own), Shop manager
if (requirement.Action == CrudActions.Read
&& (userRole != Roles.Admin
&& userRole != Roles.Editor
&& userRole != Roles.Author
&& userRole != Roles.Contributor
&& userRole != Roles.ShopManager
&& ((userRole == Roles.Author || userRole == Roles.Contributor) && resource.Any(x => x.UserId != user.Id))))
return Task.CompletedTask;
// Can Admin, Editor, Author (own), Contributor (own, not yet pubblished), Shop manager
if ((requirement.Action == CrudActions.Update || requirement.Action == CrudActions.Delete)
&& (userRole != Roles.Admin
&& userRole != Roles.Editor
&& userRole != Roles.Author
&& userRole != Roles.Contributor
&& userRole != Roles.ShopManager
&& ((userRole == Roles.Author || userRole == Roles.Contributor) && resource.Any(x => x.UserId != user.Id))
&& (userRole == Roles.Contributor && resource.Any(x => x.Published != null))))
return Task.CompletedTask;
context.Succeed(requirement);
return Task.CompletedTask;
}
}
/// <summary>
///
/// </summary>
public class FileAuthorisationRequirement : AuthorizationRequirementBase { }

View File

@ -0,0 +1,106 @@
using Core.Enumerations;
using DataProviders.Buckets;
using DataProviders.Collections;
using DomainObjects.Documents.Users;
using FileSecurityService;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using WeatherForecast.Policies.Abstractions;
namespace WeatherForecast.Policies;
/// <summary>
///
/// </summary>
public class ImageAuthorisationHandler : AuthorizationHandlerBase<ImageAuthorisationRequirement, List<BucketFile>> {
private readonly IFileSecurityService _fileSecurityService;
/// <summary>
///
/// </summary>
/// <param name="configuration"></param>
/// <param name="contextAccessor"></param>
/// <param name="siteDataProvider"></param>
/// <param name="userDataProvider"></param>
/// <param name="fileSecurityService"></param>
public ImageAuthorisationHandler(
IOptions<Configuration> configuration,
IHttpContextAccessor contextAccessor,
ISiteDataProvider siteDataProvider,
IUserDataProvider userDataProvider,
IFileSecurityService fileSecurityService
) : base(configuration, contextAccessor, siteDataProvider, userDataProvider) {
_fileSecurityService = fileSecurityService;
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="requirement"></param>
/// <param name="resource"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ImageAuthorisationRequirement requirement, List<BucketFile> resource) {
var (site, user) = GetUser(context);
if (site == null || user == null)
return Task.CompletedTask;
var userRole = GetRole(site, user);
var req = requirement.Roles.SingleOrDefault(x => x.Role == userRole);
if (req == null)
return Task.CompletedTask;
foreach (var res in resource) {
var (fileCategory, signatureResult) = _fileSecurityService.CheckFileSignature(res.Name, res.Bytes, res.ContentType);
if (!signatureResult.IsSuccess || fileCategory == null)
return Task.CompletedTask;
if (req.OwnOnly && res.UserId != user.Id)
return Task.CompletedTask;
if (req.DenyPublished && res.Published != null)
return Task.CompletedTask;
}
context.Succeed(requirement);
return Task.CompletedTask;
}
}
/// <summary>
///
/// </summary>
public class ImageRole {
/// <summary>
///
/// </summary>
public Roles Role { get; init; }
/// <summary>
///
/// </summary>
public bool DenyPublished { get; init; } = false;
/// <summary>
///
/// </summary>
public bool OwnOnly { get; init; } = false;
}
/// <summary>
///
/// </summary>
public class ImageAuthorisationRequirement : AuthorizationRequirementBase {
/// <summary>
///
/// </summary>
public List<ImageRole> Roles { get; init; }
}

View File

@ -43,31 +43,10 @@ namespace WeatherForecast.Policies
var userRole = GetRole(site, user);
// Can Admin, Shop manager
if (requirement.Action == CrudActions.Create
&& userRole != Roles.Admin
&& userRole != Roles.ShopManager)
var req = requirement.Roles.SingleOrDefault(x => x.Role == userRole);
if (req == null)
return Task.CompletedTask;
// Can Admin, Shop manager
if (requirement.Action == CrudActions.Read
&& userRole != Roles.Admin
&& userRole != Roles.ShopManager)
return Task.CompletedTask;
// Can Admin, Shop manager
if (requirement.Action == CrudActions.Update
&& userRole != Roles.Admin
&& userRole != Roles.ShopManager)
return Task.CompletedTask;
// Can Admin, Shop manager
if (requirement.Action == CrudActions.Delete
&& userRole != Roles.Admin
&& userRole != Roles.ShopManager)
return Task.CompletedTask;
context.Succeed(requirement);
return Task.CompletedTask;
@ -77,5 +56,23 @@ namespace WeatherForecast.Policies
/// <summary>
///
/// </summary>
public class ShopAuthorizationRequirement : AuthorizationRequirementBase { }
public class ShopRole {
/// <summary>
///
/// </summary>
public Roles Role { get; init; }
}
/// <summary>
///
/// </summary>
public class ShopAuthorizationRequirement : AuthorizationRequirementBase {
/// <summary>
///
/// </summary>
public List<ShopRole> Roles { get; init; }
}
}

View File

@ -0,0 +1,89 @@
using DataProviders.Buckets;
using DataProviders.Collections;
using DomainObjects.Documents.Users;
using FileSecurityService;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using WeatherForecast.Policies.Abstractions;
namespace WeatherForecast.Policies {
/// <summary>
///
/// </summary>
public class TemplateAuthorizationHandler : AuthorizationHandlerBase<TemplateAuthorisationRequirement, List<BucketFile>> {
private readonly IFileSecurityService _fileSecurityService;
/// <summary>
///
/// </summary>
/// <param name="configuration"></param>
/// <param name="contextAccessor"></param>
/// <param name="siteDataProvider"></param>
/// <param name="userDataProvider"></param>
/// <param name="fileSecurityService"></param>
public TemplateAuthorizationHandler(
IOptions<Configuration> configuration,
IHttpContextAccessor contextAccessor,
ISiteDataProvider siteDataProvider,
IUserDataProvider userDataProvider,
IFileSecurityService fileSecurityService
) : base(configuration, contextAccessor, siteDataProvider, userDataProvider) {
_fileSecurityService = fileSecurityService;
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="requirement"></param>
/// <param name="resource"></param>
/// <returns></returns>
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TemplateAuthorisationRequirement requirement, List<BucketFile> resource) {
var (site, user) = GetUser(context);
if (site == null || user == null)
return Task.CompletedTask;
var userRole = GetRole(site, user);
var req = requirement.Roles.SingleOrDefault(x => x.Role == userRole);
if (req == null)
return Task.CompletedTask;
foreach (var res in resource) {
var (fileCategory, signatureResult) = _fileSecurityService.CheckFileSignature(res.Name, res.Bytes, res.ContentType);
if (!signatureResult.IsSuccess || fileCategory == null)
return Task.CompletedTask;
}
context.Succeed(requirement);
return Task.CompletedTask;
}
}
/// <summary>
///
/// </summary>
public class TemplateRole {
/// <summary>
///
/// </summary>
public Roles Role { get; init; }
}
/// <summary>
///
/// </summary>
public class TemplateAuthorisationRequirement : AuthorizationRequirementBase {
/// <summary>
///
/// </summary>
public List<TemplateRole> Roles { get; init; }
}
}

View File

@ -21,7 +21,7 @@ namespace WeatherForecast.Services {
/// </summary>
/// <param name="requestData"></param>
/// <returns></returns>
(string?, IDomainResult) Authenticate(AuthenticationRequestModel requestData);
(string?, IDomainResult) Authenticate(PostAuthenticationRequestModel requestData);
/// <summary>
///
@ -29,7 +29,7 @@ namespace WeatherForecast.Services {
/// <param name="hostName"></param>
/// <param name="requestData"></param>
/// <returns></returns>
IDomainResult PasswordRecovery(string hostName, PasswordRecoveryRequestModel requestData);
IDomainResult PasswordRecovery(string hostName, PutPasswordRecoveryRequestModel requestData);
/// <summary>
@ -37,7 +37,7 @@ namespace WeatherForecast.Services {
/// </summary>
/// <param name="requestData"></param>
/// <returns></returns>
IDomainResult PasswordReset(PasswordResetRequestModel requestData);
IDomainResult PasswordReset(PutPasswordResetRequestModel requestData);
/// <summary>
@ -46,7 +46,7 @@ namespace WeatherForecast.Services {
/// <param name="user"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(Guid?, IDomainResult) PasswordChange(User user, PasswordChangeRequestModel requestData);
(Guid?, IDomainResult) PasswordChange(User user, PutPasswordChangeRequestModel requestData);
}
/// <summary>
@ -110,7 +110,7 @@ namespace WeatherForecast.Services {
/// </summary>
/// <param name="requestData"></param>
/// <returns></returns>
public (string?, IDomainResult) Authenticate(AuthenticationRequestModel requestData) {
public (string?, IDomainResult) Authenticate(PostAuthenticationRequestModel requestData) {
// Retrieve user from database by userName
var (user, getUserResult) = _userDataProvider.GetByUsername(requestData.Username);
@ -137,7 +137,7 @@ namespace WeatherForecast.Services {
/// <param name="requestData"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public IDomainResult PasswordRecovery(string hostName, PasswordRecoveryRequestModel requestData) {
public IDomainResult PasswordRecovery(string hostName, PutPasswordRecoveryRequestModel requestData) {
var (user, getUserResult) = _userDataProvider.GetByUsername(requestData.Username);
if (!getUserResult.IsSuccess || user == null)
return getUserResult;
@ -197,7 +197,7 @@ namespace WeatherForecast.Services {
/// </summary>
/// <param name="requestData"></param>
/// <returns></returns>
public IDomainResult PasswordReset(PasswordResetRequestModel requestData) {
public IDomainResult PasswordReset(PutPasswordResetRequestModel requestData) {
var (user, getUserResult) = _userDataProvider.GetByRecoveryToken(requestData.Token);
if (!getUserResult.IsSuccess || user == null)
@ -216,7 +216,7 @@ namespace WeatherForecast.Services {
/// <param name="user"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (Guid?, IDomainResult) PasswordChange(User user, PasswordChangeRequestModel requestData) {
public (Guid?, IDomainResult) PasswordChange(User user, PutPasswordChangeRequestModel requestData) {
user.Authentication.PasswordChange(requestData.OldPassword, requestData.NewPassword);

View File

@ -6,6 +6,7 @@ using WeatherForecast.Services.Abstractions;
using WeatherForecast.Models.Blog.Responses;
using WeatherForecast.Models.Blog.Requests;
using DomainObjects.Documents.Posts;
using WeatherForecast.Models.BlogItem.Requests;
namespace WeatherForecast.Services
{
@ -27,15 +28,15 @@ namespace WeatherForecast.Services
/// </summary>
/// <param name="blogItem"></param>
/// <returns></returns>
(BlogItemResponseModel?, IDomainResult) Get(BlogDocument blogItem);
(GetBlogItemResponseModel?, IDomainResult) Get(BlogDocument blogItem);
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(BlogItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug);
(GetBlogItemResponseModel?, IDomainResult) GetSlug(Guid siteId, GetBlogItemSlugRequestModel requestData);
/// <summary>
///
@ -43,7 +44,7 @@ namespace WeatherForecast.Services
/// <param name="blogItem"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(Guid?, IDomainResult) Update(BlogDocument blogItem, BlogItemRequestModel requestData);
(Guid?, IDomainResult) Update(BlogDocument blogItem, PutBlogItemRequestModel requestData);
}
/// <summary>
@ -97,13 +98,13 @@ namespace WeatherForecast.Services
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public (BlogItemResponseModel?, IDomainResult) Get(BlogDocument item) {
public (GetBlogItemResponseModel?, IDomainResult) Get(BlogDocument item) {
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(item.SiteId, item.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<BlogItemResponseModel?>();
return IDomainResult.Failed<GetBlogItemResponseModel?>();
return IDomainResult.Success(new BlogItemResponseModel(item, categories));
return IDomainResult.Success(new GetBlogItemResponseModel(item, categories));
}
@ -111,21 +112,21 @@ namespace WeatherForecast.Services
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (BlogItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug) {
public (GetBlogItemResponseModel?, IDomainResult) GetSlug(Guid siteId, GetBlogItemSlugRequestModel requestData) {
var (blog, getBlogItemResult) = _blogCatalogDataProvider.GetBySlug(siteId, slug);
var (blog, getBlogItemResult) = _blogCatalogDataProvider.GetBySlug(siteId, requestData.Slug);
if (!getBlogItemResult.IsSuccess || blog == null)
return IDomainResult.Failed<BlogItemResponseModel?>();
return IDomainResult.Failed<GetBlogItemResponseModel?>();
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(blog.SiteId, blog.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<BlogItemResponseModel?>();
return IDomainResult.Failed<GetBlogItemResponseModel?>();
var locale = blog.L10n.Single(x => x.Slug == slug).Locale;
var locale = blog.L10n.Single(x => x.Slug == requestData.Slug).Locale;
return IDomainResult.Success(new BlogItemResponseModel(blog, categories, locale));
return IDomainResult.Success(new GetBlogItemResponseModel(blog, categories, locale));
}
/// <summary>
@ -134,7 +135,7 @@ namespace WeatherForecast.Services
/// <param name="blogItem"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (Guid?, IDomainResult) Update(BlogDocument blogItem, BlogItemRequestModel requestData) {
public (Guid?, IDomainResult) Update(BlogDocument blogItem, PutBlogItemRequestModel requestData) {
// construct domain object from model
var newItem = requestData.ToDomainObject(blogItem.Author, blogItem.SiteId);

View File

@ -4,9 +4,9 @@ using Core.Abstractions;
using Core.Enumerations;
using DataProviders.Collections;
using WeatherForecast.Models.Responses;
using WeatherForecast.Models.Blog.Responses;
using DomainObjects.Enumerations;
using WeatherForecast.Models.BlogItem.Requests;
namespace WeatherForecast.Services {
@ -19,13 +19,9 @@ namespace WeatherForecast.Services {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="category"></param>
/// <param name="currentPage"></param>
/// <param name="itemsPerPage"></param>
/// <param name="locale"></param>
/// <param name="searchText"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(BlogItemsResponseModel?, IDomainResult) Get(Guid siteId, Guid? category, int currentPage, int itemsPerPage, string? locale, string? searchText);
(GetBlogItemsResponseModel?, IDomainResult) Get(Guid siteId, GetBlogItemsRequestModel requestData);
}
/// <summary>
@ -55,33 +51,26 @@ namespace WeatherForecast.Services {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="category"></param>
/// <param name="currentPage"></param>
/// <param name="itemsPerPage"></param>
/// <param name="locale"></param>
/// <param name="searchText"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (BlogItemsResponseModel?, IDomainResult) Get(Guid siteId, Guid? category, int currentPage, int itemsPerPage, string? locale, string? searchText) {
public (GetBlogItemsResponseModel?, IDomainResult) Get(Guid siteId, GetBlogItemsRequestModel requestData) {
var (items, result) = _blogCatalogDataProvider.GetAll(siteId, currentPage > 0 ? ((currentPage - 1) * itemsPerPage) : 0, itemsPerPage);
var (items, result) = _blogCatalogDataProvider.GetAll(siteId, requestData.CurrentPage > 0 ? ((requestData.CurrentPage - 1) * requestData.ItemsPerPage) : 0, requestData.ItemsPerPage);
if (!result.IsSuccess || items == null)
return (null, result);
var blogItems = new List<BlogItemResponseModel>();
var blogItems = new List<GetBlogItemResponseModel>();
foreach (var item in items) {
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<BlogItemsResponseModel?>();
return IDomainResult.Failed<GetBlogItemsResponseModel?>();
if (locale != null)
blogItems.Add(new BlogItemResponseModel(item, categories, Enumeration.FromDisplayName<Locales>(locale) ?? Locales.Us));
else
blogItems.Add(new BlogItemResponseModel(item, categories));
blogItems.Add(new GetBlogItemResponseModel(item, categories, requestData.Locale));
}
return blogItems.Count > 0
? IDomainResult.Success(new BlogItemsResponseModel(currentPage, 0, blogItems))
: IDomainResult.NotFound<BlogItemsResponseModel?>();
? IDomainResult.Success(new GetBlogItemsResponseModel(requestData.CurrentPage, 0, blogItems))
: IDomainResult.NotFound<GetBlogItemsResponseModel?>();
}

View File

@ -2,12 +2,12 @@
using DataProviders.Collections;
using Core.Enumerations;
using Core.Abstractions;
using WeatherForecast.Models.Category.Requests;
using WeatherForecast.Models.Category.Responses;
using DomainObjects.Enumerations;
using WeatherForecast.Models.CategoryItem.Requests;
namespace WeatherForecast.Services {
@ -22,7 +22,7 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="requestModel"></param>
/// <returns></returns>
(Guid?, IDomainResult) Post(Guid siteId, CategoryItemRequestModel requestModel);
(Guid?, IDomainResult) Post(Guid siteId, PostCategoryItemRequestModel requestModel);
/// <summary>
///
@ -30,15 +30,15 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="categoryId"></param>
/// <returns></returns>
(CategoryItemResponseModel?, IDomainResult) Get(Guid siteId, Guid categoryId);
(GetCategoryItemResponseModel?, IDomainResult) Get(Guid siteId, Guid categoryId);
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(CategoryItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug);
(GetCategoryItemResponseModel?, IDomainResult) GetSlug(Guid siteId, GetCategoryItemSlugRequestModel requestData);
/// <summary>
///
@ -47,7 +47,7 @@ namespace WeatherForecast.Services {
/// <param name="categoryId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(Guid?, IDomainResult) Update(Guid siteId, Guid categoryId, CategoryItemRequestModel requestData);
(Guid?, IDomainResult) Update(Guid siteId, Guid categoryId, PutCategoryItemRequestModel requestData);
/// <summary>
///
@ -83,7 +83,7 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="requestModel"></param>
/// <returns></returns>
public (Guid?, IDomainResult) Post(Guid siteId, CategoryItemRequestModel requestModel) {
public (Guid?, IDomainResult) Post(Guid siteId, PostCategoryItemRequestModel requestModel) {
try {
var item = requestModel.ToDomainObject(siteId);
@ -110,17 +110,17 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="categoryId"></param>
/// <returns></returns>
public (CategoryItemResponseModel?, IDomainResult) Get(Guid siteId, Guid categoryId) {
public (GetCategoryItemResponseModel?, IDomainResult) Get(Guid siteId, Guid categoryId) {
try {
var (item, result) = _categoryDataProvider.Get(siteId, categoryId);
if (!result.IsSuccess || item == null)
return (null, result);
return IDomainResult.Success(new CategoryItemResponseModel(item));
return IDomainResult.Success(new GetCategoryItemResponseModel(item));
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed<CategoryItemResponseModel?>(ex.Message);
return IDomainResult.Failed<GetCategoryItemResponseModel?>(ex.Message);
}
}
@ -128,21 +128,21 @@ namespace WeatherForecast.Services {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (CategoryItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug) {
public (GetCategoryItemResponseModel?, IDomainResult) GetSlug(Guid siteId, GetCategoryItemSlugRequestModel requestData) {
try {
var (item, result) = _categoryDataProvider.GetBySlug(siteId, slug);
var (item, result) = _categoryDataProvider.GetBySlug(siteId, requestData.Slug);
if (!result.IsSuccess || item == null)
return (null, result);
var locale = item.L10n.SingleOrDefault(x => x.Slug == slug)?.Locale ?? Locales.Us;
var locale = item.L10n.SingleOrDefault(x => x.Slug == requestData.Slug)?.Locale ?? Locales.Us;
return IDomainResult.Success(new CategoryItemResponseModel(item, locale));
return IDomainResult.Success(new GetCategoryItemResponseModel(item, locale));
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed<CategoryItemResponseModel?>(ex.Message);
return IDomainResult.Failed<GetCategoryItemResponseModel?>(ex.Message);
}
}
@ -153,7 +153,7 @@ namespace WeatherForecast.Services {
/// <param name="categoryId"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (Guid?, IDomainResult) Update(Guid siteId, Guid categoryId, CategoryItemRequestModel requestData) {
public (Guid?, IDomainResult) Update(Guid siteId, Guid categoryId, PutCategoryItemRequestModel requestData) {
try {
var (item, result) = _categoryDataProvider.Get(siteId, categoryId);
if (!result.IsSuccess || item == null)

View File

@ -5,9 +5,10 @@ using DataProviders.Collections;
using Core.Abstractions;
using Core.Enumerations;
using WeatherForecast.Models.Responses;
using WeatherForecast.Models.Category.Responses;
using DomainObjects.Enumerations;
using WeatherForecast.Models.CategoryItem.Requests;
namespace WeatherForecast.Services {
@ -20,9 +21,9 @@ namespace WeatherForecast.Services {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="locale"></param>
/// <param name="requestDat"></param>
/// <returns></returns>
(List<CategoryItemResponseModel>?, IDomainResult) Get(Guid siteId, string? locale);
(List<GetCategoryItemResponseModel>?, IDomainResult) Get(Guid siteId, GetCategoryItemsRequestModel requestData);
/// <summary>
///
@ -57,21 +58,17 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="locale"></param>
/// <returns></returns>
public (List<CategoryItemResponseModel>?, IDomainResult) Get(Guid siteId, string? locale) {
public (List<GetCategoryItemResponseModel>?, IDomainResult) Get(Guid siteId, GetCategoryItemsRequestModel requestData) {
try {
var (items, result) = _categoryDataProvider.GetAll(siteId);
if (!result.IsSuccess || items == null)
return (null, result);
if (locale != null) {
return IDomainResult.Success(items.Select(x => new CategoryItemResponseModel(x, Enumeration.FromDisplayName<Locales>(locale) ?? Locales.Us)).ToList());
}
return IDomainResult.Success(items.Select(x => new CategoryItemResponseModel(x)).ToList());
return IDomainResult.Success(items.Select(x => new GetCategoryItemResponseModel(x, requestData.Locale)).ToList());
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed<List<CategoryItemResponseModel>?>(ex.Message);
return IDomainResult.Failed<List<GetCategoryItemResponseModel>?>(ex.Message);
}
}

View File

@ -2,9 +2,9 @@
using DataProviders.Collections;
using WeatherForecast.Models.Responses;
using Core.Abstractions;
using WeatherForecast.Models.Content.Responses;
using WeatherForecast.Models.Content.Requests;
namespace WeatherForecast.Services {
@ -19,7 +19,7 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param>
/// <param name="locale"></param>
/// <returns></returns>
(ContentResponseModel?, IDomainResult) GetContent(Guid siteId, string locale);
(GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, GetContentRequestModel requestData);
}
/// <summary>
@ -45,19 +45,19 @@ namespace WeatherForecast.Services {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="locale"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (ContentResponseModel?, IDomainResult) GetContent(Guid siteId, string locale) {
public (GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, GetContentRequestModel requestData) {
try {
var (content, result) = _contentDataProvider.Get(siteId);
if (!result.IsSuccess || content == null)
return (null, result);
return IDomainResult.Success(new ContentResponseModel(content.Single(x => x.Localization.Locale == locale)));
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<ContentResponseModel?>(ex.Message);
return IDomainResult.Failed<GetContentResponseModel?>(ex.Message);
}
}
}

View File

@ -7,8 +7,10 @@ using DataProviders.Collections;
using ImageProvider;
using ImageProvider.Fonts;
using Core.Abstractions;
using WeatherForecast.Models.Responses;
using WeatherForecast.Models.File.Responses;
using WeatherForecast.Models.Images.Responses;
using Microsoft.AspNetCore.Mvc;
using DomainObjects.Documents.Users;
namespace WeatherForecast.Services {
@ -16,6 +18,30 @@ namespace WeatherForecast.Services {
///
/// </summary>
public interface IImageService {
/// <summary>
///
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
(Guid?, IDomainResult) Post(BucketFile file);
/// <summary>
///
/// </summary>
/// <param name="files"></param>
/// <returns></returns>
(List<Guid>?, IDomainResult) Post(List<BucketFile> files);
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
(GetImageResponseModel?, IDomainResult) Get([FromRoute] Guid siteId, [FromRoute] Guid? userId, [FromRoute] Guid fileId);
/// <summary>
///
/// </summary>
@ -24,7 +50,29 @@ namespace WeatherForecast.Services {
/// <param name="height"></param>
/// <param name="imageId"></param>
/// <returns></returns>
(FileResponseModel?, IDomainResult) Get(Guid siteId, int width, int height, Guid imageId);
(GetImageResponseModel?, IDomainResult) Get(Guid siteId, int width, int height, Guid imageId);
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <param name="file"></param>
/// <returns></returns>
(Guid?, IDomainResult) Update(Guid siteId, Guid? userId, Guid fileId, BucketFile file);
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
IDomainResult Delete(Guid siteId, Guid? userId, Guid fileId);
}
/// <summary>
@ -54,40 +102,107 @@ namespace WeatherForecast.Services {
_contentDataProvider = contentDataProvider;
}
/// <summary>
///
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public (Guid?, IDomainResult) Post(BucketFile file) {
return _imageBucketDataProvider.Upload(file);
}
/// <summary>
///
/// </summary>
/// <param name="files"></param>
/// <returns></returns>
public (List<Guid>?, IDomainResult) Post(List<BucketFile> files) {
return _imageBucketDataProvider.UploadMany(files);
}
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
public (GetImageResponseModel?, IDomainResult) Get(Guid siteId, Guid? userId, Guid fileId) {
var (file, downloadResult) = _imageBucketDataProvider.Download(siteId, userId, fileId);
if (!downloadResult.IsSuccess || file == null)
return IDomainResult.Failed<GetImageResponseModel?>();
return IDomainResult.Success(new GetImageResponseModel {
Name = file.Name,
Bytes = file.Bytes,
ContentType = file.ContentType
});
}
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="imageId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
public (FileResponseModel?, IDomainResult) Get(Guid siteId, int width, int height, Guid imageId) {
public (GetImageResponseModel?, IDomainResult) Get(Guid siteId, int width, int height, Guid fileId) {
try {
var (file, downloadResult) = _imageBucketDataProvider.Download(siteId, imageId);
var (file, downloadResult) = _imageBucketDataProvider.Download(siteId, fileId);
if (!downloadResult.IsSuccess || file == null)
return IDomainResult.Failed<FileResponseModel?> ();
return IDomainResult.Failed<GetImageResponseModel?>();
var (content, getContentResult) = _contentDataProvider.Get(siteId);
if (!getContentResult.IsSuccess || content == null)
return IDomainResult.Failed<FileResponseModel?>();
return IDomainResult.Failed<GetImageResponseModel?>();
var (image, transformResult) = _imageProvider.ResizeAndWatermark(file.Bytes, width, height, FontsEnum.Montserrat, FontStylesEnum.Regular, content.First().SiteName);
if (!transformResult.IsSuccess || image == null)
return IDomainResult.Failed<FileResponseModel?>();
return IDomainResult.Failed<GetImageResponseModel?>();
return IDomainResult.Success(new FileResponseModel {
return IDomainResult.Success(new GetImageResponseModel {
Name = file.Name,
Bytes = image,
ContentType = "image/jpeg" });
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed<FileResponseModel?> (ex.Message);
return IDomainResult.Failed<GetImageResponseModel?> (ex.Message);
}
}
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <param name="file"></param>
/// <returns></returns>
public (Guid?, IDomainResult) Update(Guid siteId, Guid? userId, Guid fileId, BucketFile file) {
var deleteResult = _imageBucketDataProvider.DeleteOne(siteId, userId, fileId);
if (!deleteResult.IsSuccess)
return IDomainResult.Failed<Guid?>();
var (_, fileUploadResult) = _imageBucketDataProvider.Upload(file);
if (!fileUploadResult.IsSuccess)
return IDomainResult.Failed<Guid?>();
return IDomainResult.Success(fileId);
}
/// <summary>
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="userId"></param>
/// <param name="fileId"></param>
/// <returns></returns>
public IDomainResult Delete(Guid siteId, Guid? userId, Guid fileId) {
return _imageBucketDataProvider.DeleteOne(siteId, userId, fileId);
}
}
}

View File

@ -23,7 +23,7 @@ public interface IInitializationService {
/// </summary>
/// <param name="requestData"></param>
/// <returns></returns>
IDomainResult InitializeSystem(InitializeSystemRequestModel requestData);
IDomainResult InitializeSystem(PostInitializeSystemRequestModel requestData);
}
@ -79,7 +79,7 @@ public class InitializationService : ServiceBase<InitializationService>, IInitia
/// </summary>
/// <param name="requestData"></param>
/// <returns></returns>
public IDomainResult InitializeSystem(InitializeSystemRequestModel requestData) {
public IDomainResult InitializeSystem(PostInitializeSystemRequestModel requestData) {
var userId = "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60".ToGuid();
var siteId = "404c8232-9048-4519-bfba-6e78dc7005ca".ToGuid();

View File

@ -3,11 +3,10 @@
using DataProviders.Collections;
using Core.Abstractions;
using WeatherForecast.Models.Responses;
using WeatherForecast.Models.Shop.Requests;
using DomainObjects.Documents;
using DomainObjects.Enumerations;
using WeatherForecast.Models.ShopCart.Requests;
using WeatherForecast.Models.ShopCart.Responses;
namespace WeatherForecast.Services;
@ -24,23 +23,23 @@ public interface IShopCartItemService {
/// <param name="sku"></param>
/// <param name="requestModel"></param>
/// <returns></returns>
(Guid?, IDomainResult) Post(Guid siteId, Guid userId, string sku, ShopCartItemRequestModel requestModel);
(Guid?, IDomainResult) Post(Guid siteId, Guid userId, string sku, PostShopCartItemRequestModel requestModel);
/// <summary>
///
/// </summary>
/// <param name="cartItem"></param>
/// <param name="locale"></param>
/// <returns></returns>
(ShopCartItemResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, string? locale);
(GetShopCartItemResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, GetShopCartItemRequestModel requestData);
/// <summary>
///
/// </summary>
/// <param name="cartItem"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(Guid?, IDomainResult) Update(ShopCartDocument cartItem, ShopCartItemRequestModel requestData);
(Guid?, IDomainResult) Update(ShopCartDocument cartItem, PutShopCartItemRequestModel requestData);
}
/// <summary>
@ -74,65 +73,62 @@ public class ShopCartItemService : ServiceBase<ShopCartItemService>, IShopCartIt
/// <param name="sku"></param>
/// <param name="requestModel"></param>
/// <returns></returns>
public (Guid?, IDomainResult) Post(Guid siteId, Guid userId, string sku, ShopCartItemRequestModel requestModel) {
public (Guid?, IDomainResult) Post(Guid siteId, Guid userId, string sku, PostShopCartItemRequestModel requestModel) {
var (_, getResult) = _shopCartDataProvider.Get(siteId, userId, sku);
if (getResult.IsSuccess)
return IDomainResult.Failed<Guid?>();
var (_, getResult) = _shopCartDataProvider.Get(siteId, userId, sku);
if (getResult.IsSuccess)
return IDomainResult.Failed<Guid?>();
var item = requestModel.ToDomainObject(sku, userId, siteId);
var item = requestModel.ToDomainObject(sku, userId, siteId);
var (id, insertResult) = _shopCartDataProvider.Insert(item);
var (id, insertResult) = _shopCartDataProvider.Insert(item);
if (!insertResult.IsSuccess)
return IDomainResult.Failed<Guid?>();
if (!insertResult.IsSuccess)
return IDomainResult.Failed<Guid?>();
return IDomainResult.Success(id);
return IDomainResult.Success(id);
}
/// <summary>
///
/// </summary>
/// <param name="cartItem"></param>
/// <param name="locale"></param>
/// <returns></returns>
public (ShopCartItemResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, string? locale) {
var (item, result) = _shopCatalogDataProvider.Get(cartItem.SiteId, cartItem.Sku);
if (!result.IsSuccess || item == null) {
var delteResult = _shopCartDataProvider.Delete(cartItem.Id);
if (!delteResult.IsSuccess)
return (null, delteResult);
return IDomainResult.NotFound<ShopCartItemResponseModel?>();
}
else
return IDomainResult.Success(new ShopCartItemResponseModel(item, cartItem, Enumeration.FromDisplayName<Locales>(locale ?? "en-US")));
}
/// <summary>
///
/// </summary>
/// <param name="cartItem"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (Guid?, IDomainResult) Update(ShopCartDocument cartItem, ShopCartItemRequestModel requestData) {
public (GetShopCartItemResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, GetShopCartItemRequestModel requestData) {
// construct domain object from model
var newItem = requestData.ToDomainObject(cartItem.Sku, cartItem.UserId, cartItem.SiteId);
newItem.Id = cartItem.Id;
newItem.Created = cartItem.Created;
var (item, result) = _shopCatalogDataProvider.Get(cartItem.SiteId, cartItem.Sku);
if (!result.IsSuccess || item == null) {
var delteResult = _shopCartDataProvider.Delete(cartItem.Id);
if (!delteResult.IsSuccess)
return (null, delteResult);
if (!cartItem.Equals(newItem)) {
var (id, updateResult) = _shopCartDataProvider.Update(newItem);
if (!updateResult.IsSuccess || id == null)
return (null, updateResult);
}
return IDomainResult.NotFound<GetShopCartItemResponseModel?>();
}
else
return IDomainResult.Success(new GetShopCartItemResponseModel(item, cartItem, requestData.Locale));
}
return IDomainResult.Success(cartItem.Id);
/// <summary>
///
/// </summary>
/// <param name="cartItem"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (Guid?, IDomainResult) Update(ShopCartDocument cartItem, PutShopCartItemRequestModel requestData) {
// construct domain object from model
var newItem = requestData.ToDomainObject(cartItem.Sku, cartItem.UserId, cartItem.SiteId);
newItem.Id = cartItem.Id;
newItem.Created = cartItem.Created;
if (!cartItem.Equals(newItem)) {
var (id, updateResult) = _shopCartDataProvider.Update(newItem);
if (!updateResult.IsSuccess || id == null)
return (null, updateResult);
}
return IDomainResult.Success(cartItem.Id);
}
}

View File

@ -3,17 +3,18 @@
using DataProviders.Collections;
using Core.Abstractions;
using WeatherForecast.Models.Responses;
using DomainObjects.Documents;
using DomainObjects.Enumerations;
using WeatherForecast.Models.ShopCart.Requests;
using WeatherForecast.Models.ShopCart.Responses;
namespace WeatherForecast.Services {
namespace WeatherForecast.Services
{
/// <summary>
///
/// </summary>
public interface IShopCartItemsService {
/// <summary>
///
/// </summary>
public interface IShopCartItemsService {
/// <summary>
///
@ -21,7 +22,7 @@ namespace WeatherForecast.Services {
/// <param name="cartItems"></param>
/// <param name="locale"></param>
/// <returns></returns>
(List<ShopCartItemResponseModel>?, IDomainResult) Get(List<ShopCartDocument> cartItems, string? locale);
(List<GetShopCartItemResponseModel>?, IDomainResult) Get(List<ShopCartDocument> cartItems, GetShopCartItemsController requestData);
}
/// <summary>
@ -51,11 +52,11 @@ namespace WeatherForecast.Services {
///
/// </summary>
/// <param name="cartItems"></param>
/// <param name="locale"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (List<ShopCartItemResponseModel>?, IDomainResult) Get(List<ShopCartDocument> cartItems, string? locale) {
public (List<GetShopCartItemResponseModel>?, IDomainResult) Get(List<ShopCartDocument> cartItems, GetShopCartItemsController requestData) {
var items = new List<ShopCartItemResponseModel>();
var items = new List<GetShopCartItemResponseModel>();
foreach (var cartItem in cartItems) {
var (item, result) = _shopCatalogDataProvider.Get(cartItem.Id, cartItem.Sku);
if (!result.IsSuccess || item == null) {
@ -64,12 +65,12 @@ namespace WeatherForecast.Services {
return (null, delteResult);
}
else
items.Add(new ShopCartItemResponseModel(item, cartItem, Enumeration.FromDisplayName<Locales>(locale ?? "en-US")));
items.Add(new GetShopCartItemResponseModel(item, cartItem, requestData.Locale));
}
return items.Count > 0
? IDomainResult.Success(items)
: IDomainResult.NotFound<List<ShopCartItemResponseModel>?>();
: IDomainResult.NotFound<List<GetShopCartItemResponseModel>?>();
}
}
}

View File

@ -28,7 +28,7 @@ namespace WeatherForecast.Services
/// </summary>
/// <param name="shopItem"></param>
/// <returns></returns>
(ShopItemResponseModel?, IDomainResult) Get(ShopDocument shopItem);
(GetShopItemResponseModel?, IDomainResult) Get(ShopDocument shopItem);
/// <summary>
///
@ -36,7 +36,7 @@ namespace WeatherForecast.Services
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <returns></returns>
(ShopItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug);
(GetShopItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug);
/// <summary>
///
@ -45,7 +45,7 @@ namespace WeatherForecast.Services
/// <param name="sku"></param>
/// <param name="requestData"></param>
/// <returns></returns>
(Guid?, IDomainResult) Update(Guid siteId, string sku, ShopItemRequestModel requestData);
(Guid?, IDomainResult) Update(Guid siteId, string sku, PutShopItemRequestModel requestData);
}
/// <summary>
@ -101,12 +101,12 @@ namespace WeatherForecast.Services
/// </summary>
/// <param name="shopItem"></param>
/// <returns></returns>
public (ShopItemResponseModel?, IDomainResult) Get(ShopDocument shopItem) {
public (GetShopItemResponseModel?, IDomainResult) Get(ShopDocument shopItem) {
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(shopItem.SiteId, shopItem.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<ShopItemResponseModel?>();
return IDomainResult.Failed<GetShopItemResponseModel?>();
return IDomainResult.Success(new ShopItemResponseModel(shopItem, categories));
return IDomainResult.Success(new GetShopItemResponseModel(shopItem, categories));
}
/// <summary>
@ -115,7 +115,7 @@ namespace WeatherForecast.Services
/// <param name="siteId"></param>
/// <param name="slug"></param>
/// <returns></returns>
public (ShopItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug) {
public (GetShopItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug) {
try {
var (item, result) = _shopCatalogDataProvider.GetBySlug(siteId, slug);
@ -126,13 +126,13 @@ namespace WeatherForecast.Services
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<ShopItemResponseModel?>();
return IDomainResult.Failed<GetShopItemResponseModel?>();
return IDomainResult.Success(new ShopItemResponseModel(item, categories, locale));
return IDomainResult.Success(new GetShopItemResponseModel(item, categories, locale));
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed<ShopItemResponseModel?>(ex.Message);
return IDomainResult.Failed<GetShopItemResponseModel?>(ex.Message);
}
}
@ -143,7 +143,7 @@ namespace WeatherForecast.Services
/// <param name="sku"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (Guid?, IDomainResult) Update(Guid siteId, string sku, ShopItemRequestModel requestData) {
public (Guid?, IDomainResult) Update(Guid siteId, string sku, PutShopItemRequestModel requestData) {
var (item, getResult) = _shopCatalogDataProvider.Get(siteId, sku);
if (!getResult.IsSuccess || item == null)

View File

@ -6,9 +6,10 @@ using Core.Abstractions;
using Core.Enumerations;
using WeatherForecast.Models;
using WeatherForecast.Models.Responses;
using WeatherForecast.Models.Shop.Responses;
using DomainObjects.Enumerations;
using WeatherForecast.Models.Shop.Requests;
namespace WeatherForecast.Services {
@ -27,7 +28,7 @@ namespace WeatherForecast.Services {
/// <param name="locale"></param>
/// <param name="searchText"></param>
/// <returns></returns>
(ShopItemsResponseModel?, IDomainResult) Get(Guid siteId, Guid? category, int currentPage, int itemsPerPage, string? locale, string? searchText);
(GetShopItemsResponseModel?, IDomainResult) Get(Guid siteId, GetShopItemsRequestModel requestData);
/// <summary>
///
@ -64,40 +65,32 @@ namespace WeatherForecast.Services {
///
/// </summary>
/// <param name="siteId"></param>
/// <param name="category"></param>
/// <param name="currentPage"></param>
/// <param name="itemsPerPage"></param>
/// <param name="locale"></param>
/// <param name="searchText"></param>
/// <param name="requestData"></param>
/// <returns></returns>
public (ShopItemsResponseModel?, IDomainResult) Get(Guid siteId, Guid? category, int currentPage, int itemsPerPage, string? locale, string? searchText) {
public (GetShopItemsResponseModel?, IDomainResult) Get(Guid siteId, GetShopItemsRequestModel requestData) {
try {
var (items, result) = _shopCatalogDataProvider.GetAll(siteId, currentPage > 0 ? ((currentPage - 1) * itemsPerPage) : 0, itemsPerPage);
var (items, result) = _shopCatalogDataProvider.GetAll(siteId, requestData.CurrentPage > 0 ? ((requestData.CurrentPage - 1) * requestData.ItemsPerPage) : 0, requestData.ItemsPerPage);
if (!result.IsSuccess || items == null)
return (null, result);
var shopItems = new List<ShopItemResponseModel>();
var shopItems = new List<GetShopItemResponseModel>();
foreach (var item in items) {
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<ShopItemsResponseModel?>();
return IDomainResult.Failed<GetShopItemsResponseModel?>();
if (locale != null)
shopItems.Add(new ShopItemResponseModel(item, categories, Enumeration.FromDisplayName<Locales>(locale) ?? Locales.Us));
else
shopItems.Add(new ShopItemResponseModel(item, categories));
shopItems.Add(new GetShopItemResponseModel(item, categories, requestData.Locale));
}
return shopItems.Count > 0
? IDomainResult.Success(new ShopItemsResponseModel(currentPage, 0, shopItems))
: IDomainResult.NotFound<ShopItemsResponseModel?>();
? IDomainResult.Success(new GetShopItemsResponseModel(requestData.CurrentPage, 0, shopItems))
: IDomainResult.NotFound<GetShopItemsResponseModel?>();
}
catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception");
return IDomainResult.Failed<ShopItemsResponseModel?>(ex.Message);
return IDomainResult.Failed<GetShopItemsResponseModel?>(ex.Message);
}
}

View File

@ -16,10 +16,9 @@ public interface ITemplateService {
/// <summary>
///
/// </summary>
/// <param name="requestData"></param>
/// <param name="file"></param>
/// <returns></returns>
(Guid?, IDomainResult) Post(PostTemplateRequestModel requestData, BucketFile file);
(Guid?, IDomainResult) Post(BucketFile file);
/// <summary>
///
@ -53,10 +52,9 @@ public class TemplateService : ServiceBase<TemplateService>, ITemplateService {
/// <summary>
///
/// </summary>
/// <param name="requestData"></param>
/// <param name="file"></param>
/// <returns></returns>
public (Guid?, IDomainResult) Post(PostTemplateRequestModel requestData, BucketFile file) {
public (Guid?, IDomainResult) Post(BucketFile file) {
var (fileId, uploadFileResult) = _templateBucketDataProvider.Upload(file);
if (!uploadFileResult.IsSuccess || fileId == null)

View File

@ -80,7 +80,7 @@ namespace WeatherForecast {
#region Policy Handlers
services.AddScoped<IAuthorizationHandler, BlogAuthorizationHandler>();
services.AddScoped<IAuthorizationHandler, CategoryAuthorizationHandler>();
services.AddScoped<IAuthorizationHandler, FileAuthorisationHandler>();
services.AddScoped<IAuthorizationHandler, ImageAuthorisationHandler>();
services.AddScoped<IAuthorizationHandler, ShopAuthorizationHandler>();
services.AddScoped<IAuthorizationHandler, ShopCartAuthorizationHandler>();
#endregion

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.101439=(addr="019181e43493ac119281e4c3feb5439381e4de446160808080e301ffc0e3010fc0",order=101439,time=1675717350,size=81920,newest_start_durable_ts=0,oldest_start_ts=0,newest_txn=462,newest_stop_durable_ts=0,newest_stop_ts=-1,newest_stop_txn=-11,prepare=0,write_gen=304767,run_write_gen=304099)),checkpoint_backup_info=,checkpoint_lsn=(40,185856)
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.118734=(addr="018381e4bd87c4eb8481e4a37fee9f8581e424811b00808080e3027fc0e3010fc0",order=118734,time=1678822225,size=81920,newest_start_durable_ts=0,oldest_start_ts=0,newest_txn=1306,newest_stop_durable_ts=0,newest_stop_ts=-1,newest_stop_txn=-11,prepare=0,write_gen=356701,run_write_gen=354752)),checkpoint_backup_info=,checkpoint_lsn=(50,460160)

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