(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 { namespace Core.Abstractions.Models {
public abstract class RequestModelBase : ModelBase, IValidatableObject { public abstract class RequestModelBase : ModelBase {
public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext); // public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
} }
public abstract class RequestModelBase<T> : ModelBase, IValidatableObject { //public abstract class RequestModelBase<T> : ModelBase, IValidatableObject {
public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext); // public abstract IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
} //}
} }

View File

@ -1,9 +1,31 @@
using Core.Abstractions; using Core.Abstractions;
using System.Diagnostics.CodeAnalysis;
namespace Core.Enumerations; 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 Image = new(0, "image");
public static MediaTypes Video = new(1, "video"); public static MediaTypes Video = new(1, "video");
public static MediaTypes Document = new(1, "document"); public static MediaTypes Document = new(1, "document");
private MediaTypes(int id, string displayName) : base(id, displayName) { } 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 Id { get; private set; }
public Guid SiteId { 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; } public DateTime? Published { get; private set; }

View File

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

View File

@ -2,8 +2,12 @@
namespace DomainObjects.Documents.Users; namespace DomainObjects.Documents.Users;
public class Roles : Enumeration public class Roles : Enumeration {
{
/// <summary>
///
/// </summary>
public static readonly Roles Everyone = new(-1, "Everyone");
/// <summary> /// <summary>
/// The most powerful user role because it gives you access to everything. As the website owner, this should be your role /// The most powerful user role because it gives you access to everything. As the website owner, this should be your role
@ -41,5 +45,4 @@ public class Roles : Enumeration
public static readonly Roles ShopManager = new(6, "Shop manager"); public static readonly Roles ShopManager = new(6, "Shop manager");
private Roles(int id, string displayName) : base(id, displayName) { } private Roles(int id, string displayName) : base(id, displayName) { }
} }

View File

@ -1,10 +1,32 @@
using Core.Abstractions; using Core.Abstractions;
using System.Diagnostics.CodeAnalysis;
namespace DomainObjects.Enumerations; 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 Us = new(0, "en-US");
public static Locales Ru = new(1, "ru-RU"); public static Locales Ru = new(1, "ru-RU");
public static Locales It = new(2, "it-IT"); public static Locales It = new(2, "it-IT");
private Locales(int id, string displayName) : base (id, displayName) { } 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 Core.Abstractions;
using System.Diagnostics.CodeAnalysis;
namespace DomainObjects.Enumerations; 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 Html = new(0, "HTML");
public static readonly TextFormat Md = new(1, "MD"); public static readonly TextFormat Md = new(1, "MD");
private TextFormat(int id, string displayName) : base(id, displayName) { } 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> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("[action]")] [HttpPost("[action]")]
public IActionResult Authenticate([FromBody] AuthenticationRequestModel requestData) { public IActionResult Authenticate([FromBody] PostAuthenticationRequestModel requestData) {
var result = _accountService.Authenticate(requestData); var result = _accountService.Authenticate(requestData);
return result.ToActionResult(); return result.ToActionResult();
} }
@ -53,7 +53,17 @@ public class AccountController : ControllerBase {
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("[action]")] [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(); return BadRequest();
} }
@ -65,7 +75,7 @@ public class AccountController : ControllerBase {
/// <returns></returns> /// <returns></returns>
/// <exception cref="NotImplementedException"></exception> /// <exception cref="NotImplementedException"></exception>
[HttpPut($"{_password}/[action]")] [HttpPut($"{_password}/[action]")]
public IActionResult Recovery([FromBody] PasswordRecoveryRequestModel requestData) { public IActionResult Recovery([FromBody] PutPasswordRecoveryRequestModel requestData) {
var hostName = Request?.Headers["X-Forwarded-Host"].FirstOrDefault(); var hostName = Request?.Headers["X-Forwarded-Host"].FirstOrDefault();
if (hostName == null) if (hostName == null)
@ -83,7 +93,7 @@ public class AccountController : ControllerBase {
/// <returns></returns> /// <returns></returns>
/// <exception cref="NotImplementedException"></exception> /// <exception cref="NotImplementedException"></exception>
[HttpPut($"{_password}/[action]")] [HttpPut($"{_password}/[action]")]
public IActionResult Reset([FromBody] PasswordResetRequestModel requestData) { public IActionResult Reset([FromBody] PutPasswordResetRequestModel requestData) {
var result = _accountService.PasswordReset(requestData); var result = _accountService.PasswordReset(requestData);
return result.ToActionResult(); return result.ToActionResult();
} }
@ -96,7 +106,7 @@ public class AccountController : ControllerBase {
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
[HttpPut($"{_password}/[action]/{{userId}}")] [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); var (user, getUserResult) = _userDataProvider.Get(userId);
if (!getUserResult.IsSuccess || user == null) if (!getUserResult.IsSuccess || user == null)

View File

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

View File

@ -8,6 +8,7 @@ using WeatherForecast.Policies;
using Core.Enumerations; using Core.Enumerations;
using DataProviders.Collections; using DataProviders.Collections;
using WeatherForecast.Models.Requests; using WeatherForecast.Models.Requests;
using WeatherForecast.Models.BlogItem.Requests;
namespace WeatherForecast.Controllers; namespace WeatherForecast.Controllers;
@ -43,35 +44,12 @@ public class BlogItemsController : ControllerBase {
/// ///
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="category"></param> /// <param name="requestData"></param>
/// <param name="searchText"></param>
/// <param name="currentPage"></param>
/// <param name="itemsPerPage"></param>
/// <param name="locale"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet("{siteId}")] [HttpGet("{siteId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] Guid? category, [FromQuery] string? searchText, [FromQuery] int? currentPage, [FromQuery] int? itemsPerPage, [FromQuery] string? locale) { public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetBlogItemsRequestModel requestData) {
var result = _blogItemsService.Get(siteId, category, currentPage ?? 1, itemsPerPage ?? 8, locale, searchText); var result = _blogItemsService.Get(siteId, requestData);
return result.ToActionResult(); return result.ToActionResult();
} }
#endregion #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 WeatherForecast.Policies;
using Core.Enumerations; using Core.Enumerations;
using WeatherForecast.Models.Category.Requests; using WeatherForecast.Models.Category.Requests;
using WeatherForecast.Models.CategoryItem.Requests;
using DomainObjects.Documents.Users;
namespace WeatherForecast.Controllers; namespace WeatherForecast.Controllers;
@ -38,24 +40,29 @@ public class CategoryItemController : ControllerBase {
/// ///
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="slug"></param> /// <param name="requestData"></param>
[HttpGet("{siteId}")] [HttpGet("{siteId}")]
public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] string slug) { public IActionResult GetSlug([FromRoute] Guid siteId, [FromQuery] GetCategoryItemSlugRequestModel requestData) {
var result = _categoryItemService.GetSlug(siteId, slug); var result = _categoryItemService.GetSlug(siteId, requestData);
return result.ToActionResult(); return result.ToActionResult();
} }
#endregion #endregion
/// <summary> /// <summary>
/// /// Can Admin, Editor, Shop manager
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("{siteId}")] [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 { 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) { })).Succeeded) {
var result = _categoryItemService.Post(siteId, requestData); var result = _categoryItemService.Post(siteId, requestData);
return result.ToActionResult(); return result.ToActionResult();
@ -67,6 +74,7 @@ public class CategoryItemController : ControllerBase {
/// <summary> /// <summary>
/// Returns full object /// Returns full object
/// Can Admin, Editor, Author, Contributor, Shop manager
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="categoryId"></param> /// <param name="categoryId"></param>
@ -74,7 +82,14 @@ public class CategoryItemController : ControllerBase {
[HttpGet("{siteId}/{categoryId}")] [HttpGet("{siteId}/{categoryId}")]
public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid categoryId) { public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid categoryId) {
if ((await _authorizationService.AuthorizeAsync(User, null, new CategoryAuthorizationRequirement { if ((await _authorizationService.AuthorizeAsync(User, null, new CategoryAuthorizationRequirement {
Action = CrudActions.Read 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) { })).Succeeded) {
var result = _categoryItemService.Get(siteId, categoryId); var result = _categoryItemService.Get(siteId, categoryId);
return result.ToActionResult(); return result.ToActionResult();
@ -85,16 +100,21 @@ public class CategoryItemController : ControllerBase {
} }
/// <summary> /// <summary>
/// /// Can Admin, Editor, Shop manager
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="categoryId"></param> /// <param name="categoryId"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
[HttpPut("{siteId}/{categoryId}")] [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 { 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) { })).Succeeded) {
var result = _categoryItemService.Update(siteId, categoryId, requestData); var result = _categoryItemService.Update(siteId, categoryId, requestData);
return result.ToActionResult(); return result.ToActionResult();
@ -104,7 +124,7 @@ public class CategoryItemController : ControllerBase {
} }
/// <summary> /// <summary>
/// /// Can Admin only
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="categoryId"></param> /// <param name="categoryId"></param>
@ -112,7 +132,10 @@ public class CategoryItemController : ControllerBase {
[HttpDelete("{siteId}/{categoryId}")] [HttpDelete("{siteId}/{categoryId}")]
public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid categoryId) { public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid categoryId) {
if ((await _authorizationService.AuthorizeAsync(User, null, new CategoryAuthorizationRequirement { if ((await _authorizationService.AuthorizeAsync(User, null, new CategoryAuthorizationRequirement {
Action = CrudActions.Delete Action = CrudActions.Delete,
Roles = new List<CategoryRole> {
new CategoryRole { Role = Roles.Admin }
}
})).Succeeded) { })).Succeeded) {
var result = _categoryItemService.Delete(siteId, categoryId); var result = _categoryItemService.Delete(siteId, categoryId);
return result.ToActionResult(); return result.ToActionResult();

View File

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

View File

@ -6,6 +6,8 @@ using DomainResults.Mvc;
using DataProviders.Buckets; using DataProviders.Buckets;
using WeatherForecast.Services; using WeatherForecast.Services;
using WeatherForecast.Policies;
using DomainObjects.Documents.Users;
namespace WeatherForecast.Controllers; namespace WeatherForecast.Controllers;
@ -18,18 +20,22 @@ public class DkimController : ControllerBase {
private readonly IAuthorizationService _authorizationService; private readonly IAuthorizationService _authorizationService;
private readonly IDkimBucketDataProvider _dkimBucketDataProvider;
private readonly IDkimService _dkimService; private readonly IDkimService _dkimService;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="authorizationService"></param> /// <param name="authorizationService"></param>
/// <param name="dkimBucketDataProvider"></param>
/// <param name="dkimService"></param> /// <param name="dkimService"></param>
public DkimController( public DkimController(
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
IDkimBucketDataProvider dkimBucketDataProvider,
IDkimService dkimService IDkimService dkimService
) { ) {
_authorizationService = authorizationService; _authorizationService = authorizationService;
_dkimBucketDataProvider = dkimBucketDataProvider;
_dkimService = dkimService; _dkimService = dkimService;
} }
@ -37,22 +43,33 @@ public class DkimController : ControllerBase {
/// ///
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="file"></param> /// <param name="formFile"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("{siteId}")] [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(); return IDomainResult.Failed().ToActionResult();
using var ms = new MemoryStream(); 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);
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 result.ToActionResult();
} }
return Unauthorized();
}
/// <summary> /// <summary>
/// Delete private dkim cert /// Delete private dkim cert
/// </summary> /// </summary>
@ -60,9 +77,23 @@ public class DkimController : ControllerBase {
/// <param name="fileId"></param> /// <param name="fileId"></param>
/// <returns></returns> /// <returns></returns>
[HttpDelete("{siteId}/{fileId}")] [HttpDelete("{siteId}/{fileId}")]
public IActionResult Delete([FromRoute] Guid siteId, [FromRoute] Guid fileId) { public async Task<IActionResult> Delete([FromRoute] Guid siteId, [FromRoute] Guid fileId) {
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); var result = _dkimService.Delete(siteId, fileId);
return result.ToActionResult(); 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 WeatherForecast.Services;
using DomainResults.Mvc; using DomainResults.Mvc;
using Core.Enumerations;
using DataProviders.Buckets;
using DomainResults.Common;
using WeatherForecast.Policies;
using DomainObjects.Documents.Users;
namespace WeatherForecast.Controllers; namespace WeatherForecast.Controllers;
@ -14,24 +19,121 @@ namespace WeatherForecast.Controllers;
public class ImageController : ControllerBase { public class ImageController : ControllerBase {
private readonly IAuthorizationService _authorizationService; private readonly IAuthorizationService _authorizationService;
private readonly IImageBucketDataProvider _imageBucketDataProvider;
private readonly IImageService _imageService; private readonly IImageService _imageService;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="authorizationService"></param> /// <param name="authorizationService"></param>
/// <param name="imageBucketDataProvider"></param>
/// <param name="imgeService"></param> /// <param name="imgeService"></param>
public ImageController( public ImageController(
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
IImageBucketDataProvider imageBucketDataProvider,
IImageService imgeService IImageService imgeService
) { ) {
_authorizationService = authorizationService; _authorizationService = authorizationService;
_imageBucketDataProvider = imageBucketDataProvider;
_imageService = imgeService; _imageService = imgeService;
} }
#region Authless methods #region Post
/// <summary> /// <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> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="width"></param> /// <param name="width"></param>
@ -53,4 +155,114 @@ public class ImageController : ControllerBase {
} }
#endregion #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 Core.Enumerations;
using DataProviders;
using DataProviders.Buckets; using DataProviders.Buckets;
using DomainObjects.Documents.Users;
using DomainResults.Common; using DomainResults.Common;
using DomainResults.Mvc; using DomainResults.Mvc;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using WeatherForecast.Policies; using WeatherForecast.Policies;
using WeatherForecast.Services;
namespace WeatherForecast.Controllers; namespace WeatherForecast.Controllers;
@ -14,22 +16,26 @@ namespace WeatherForecast.Controllers;
/// </summary> /// </summary>
[AllowAnonymous] [AllowAnonymous]
[Route("api/[controller]")] [Route("api/[controller]")]
public class FilesController : ControllerBase { public class ImagesController : ControllerBase {
private readonly IAuthorizationService _authorizationService; private readonly IAuthorizationService _authorizationService;
private readonly IImageBucketDataProvider _imageBucketDataProvider; private readonly IImageBucketDataProvider _imageBucketDataProvider;
private readonly IImageService _imageService;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="authorizationService"></param> /// <param name="authorizationService"></param>
/// <param name="imageBucketDataProvider"></param> /// <param name="imageBucketDataProvider"></param>
public FilesController( /// <param name="imageService"></param>
public ImagesController(
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
IImageBucketDataProvider imageBucketDataProvider IImageBucketDataProvider imageBucketDataProvider,
IImageService imageService
) { ) {
_authorizationService = authorizationService; _authorizationService = authorizationService;
_imageBucketDataProvider = imageBucketDataProvider; _imageBucketDataProvider = imageBucketDataProvider;
_imageService = imageService;
} }
/// <summary> /// <summary>
@ -40,7 +46,10 @@ public class FilesController : ControllerBase {
/// <param name="file"></param> /// <param name="file"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("{siteId}/{userId}")] [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))) if (file.Any(x => !(x.Length > 0)))
return IDomainResult.Failed().ToActionResult(); return IDomainResult.Failed().ToActionResult();
@ -48,36 +57,31 @@ public class FilesController : ControllerBase {
var newFiles = file.Select(x => { var newFiles = file.Select(x => {
using var ms = new MemoryStream(); using var ms = new MemoryStream();
x.CopyTo(ms); 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(); }).ToList();
if ((await _authorizationService.AuthorizeAsync(User, newFiles, new FileAuthorisationRequirement {
Action = CrudActions.Create var authorizationResult = await _authorizationService.AuthorizeAsync(User, newFiles, new ImageAuthorisationRequirement {
})).Succeeded) { Action = CrudActions.Create,
var result = _imageBucketDataProvider.UploadMany(newFiles); 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 result.ToActionResult();
} }
return Unauthorized(); 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> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public IActionResult InitializeSystem([FromBody] InitializeSystemRequestModel requestData) { public IActionResult InitializeSystem([FromBody] PostInitializeSystemRequestModel requestData) {
var result = _initializationService.InitializeSystem(requestData); var result = _initializationService.InitializeSystem(requestData);
return result.ToActionResult(); return result.ToActionResult();

View File

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

View File

@ -7,6 +7,7 @@ using WeatherForecast.Services;
using WeatherForecast.Policies; using WeatherForecast.Policies;
using Core.Enumerations; using Core.Enumerations;
using DataProviders.Collections; using DataProviders.Collections;
using WeatherForecast.Models.ShopCart.Requests;
namespace WeatherForecast.Controllers; namespace WeatherForecast.Controllers;
@ -42,7 +43,7 @@ public class ShopCartItemsController : ControllerBase {
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpGet("{siteId}/{userId}")] [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); var (cartItems, getCartItemsResult) = _shopCartDataProvider.GetAll(siteId, userId);
if (!getCartItemsResult.IsSuccess || cartItems == null) if (!getCartItemsResult.IsSuccess || cartItems == null)
@ -51,26 +52,10 @@ public class ShopCartItemsController : ControllerBase {
if ((await _authorizationService.AuthorizeAsync(User, cartItems, new ShopCartAuthorizationRequirement { if ((await _authorizationService.AuthorizeAsync(User, cartItems, new ShopCartAuthorizationRequirement {
Action = CrudActions.Read Action = CrudActions.Read
})).Succeeded) { })).Succeeded) {
var result = _shopCartItemsService.Get(cartItems, locale); var result = _shopCartItemsService.Get(cartItems, requestData);
return result.ToActionResult(); return result.ToActionResult();
} }
return Unauthorized(); 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 DomainResults.Common;
using Extensions; using Extensions;
using DomainObjects.Documents.Posts; using DomainObjects.Documents.Posts;
using DomainObjects.Documents.Users;
namespace WeatherForecast.Controllers; namespace WeatherForecast.Controllers;
@ -56,14 +57,14 @@ public class ShopItemController : ControllerBase {
#endregion #endregion
/// <summary> /// <summary>
/// /// Can Admin, Shop manager
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="sku"></param> /// <param name="sku"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("{siteId}/{sku}")] [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(); var userId = User?.Identity?.Name?.ToNullableGuid();
if (userId == null) if (userId == null)
@ -72,7 +73,11 @@ public class ShopItemController : ControllerBase {
var shopItem = requestData.ToDomainObject(sku, userId.Value, siteId); var shopItem = requestData.ToDomainObject(sku, userId.Value, siteId);
if ((await _authorizationService.AuthorizeAsync(User, new List<ShopDocument> { shopItem }, new ShopAuthorizationRequirement { 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) { })).Succeeded) {
var result = _shopItemService.Post(shopItem); var result = _shopItemService.Post(shopItem);
@ -84,6 +89,7 @@ public class ShopItemController : ControllerBase {
/// <summary> /// <summary>
/// Returns full object /// Returns full object
/// Can Admin, Shop manager
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="sku"></param> /// <param name="sku"></param>
@ -96,7 +102,11 @@ public class ShopItemController : ControllerBase {
return getShopItemResult.ToActionResult(); return getShopItemResult.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<ShopDocument> { shopItem }, new ShopAuthorizationRequirement { 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) { })).Succeeded) {
var result = _shopItemService.Get(shopItem); var result = _shopItemService.Get(shopItem);
return result.ToActionResult(); return result.ToActionResult();
@ -106,21 +116,25 @@ public class ShopItemController : ControllerBase {
} }
/// <summary> /// <summary>
/// /// Can Admin, Shop manager
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="sku"></param> /// <param name="sku"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
[HttpPut("{siteId}/{sku}")] [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); var (shopItem, getShopItemResult) = _shopCatalogDataProvider.Get(siteId, sku);
if (!getShopItemResult.IsSuccess || shopItem == null) if (!getShopItemResult.IsSuccess || shopItem == null)
return getShopItemResult.ToActionResult(); return getShopItemResult.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<ShopDocument> { shopItem }, new ShopAuthorizationRequirement { 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) { })).Succeeded) {
var result = _shopItemService.Update(siteId, sku, requestData); var result = _shopItemService.Update(siteId, sku, requestData);
return result.ToActionResult(); return result.ToActionResult();
@ -130,7 +144,7 @@ public class ShopItemController : ControllerBase {
} }
/// <summary> /// <summary>
/// /// Can Admin, Shop manager
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="sku"></param> /// <param name="sku"></param>
@ -143,7 +157,11 @@ public class ShopItemController : ControllerBase {
return getShopItemResult.ToActionResult(); return getShopItemResult.ToActionResult();
if ((await _authorizationService.AuthorizeAsync(User, new List<ShopDocument> { shopItem }, new ShopAuthorizationRequirement { 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) { })).Succeeded) {
var result = _shopCatalogDataProvider.Delete(shopItem.Id); var result = _shopCatalogDataProvider.Delete(shopItem.Id);
return result.ToActionResult(); return result.ToActionResult();

View File

@ -5,6 +5,7 @@ using DomainResults.Mvc;
using WeatherForecast.Services; using WeatherForecast.Services;
using DataProviders.Collections; using DataProviders.Collections;
using WeatherForecast.Models.Shop.Requests;
namespace WeatherForecast.Controllers; namespace WeatherForecast.Controllers;
@ -40,27 +41,12 @@ public class ShopItemsController : ControllerBase {
/// ///
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="category"></param> /// <param name="requestData"></param>
/// <param name="currentPage"></param>
/// <param name="itemsPerPage"></param>
/// <param name="locale"></param>
/// <param name="searchText"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet("{siteId}")] [HttpGet("{siteId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] Guid? category, [FromQuery] int? currentPage, [FromQuery] int? itemsPerPage, [FromQuery] string? locale, [FromQuery] string? searchText) { public IActionResult Get([FromRoute] Guid siteId, [FromQuery] GetShopItemsRequestModel requestData) {
var result = _shopItemsService.Get(siteId, category, currentPage ?? 1, itemsPerPage ?? 8, locale, searchText); var result = _shopItemsService.Get(siteId, requestData);
return result.ToActionResult(); return result.ToActionResult();
} }
#endregion #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.Services;
using WeatherForecast.Models.Template.Requests; using WeatherForecast.Models.Template.Requests;
using Core.Binders; using Core.Binders;
using Core.Enumerations;
using DomainObjects.Documents.Users;
using WeatherForecast.Policies;
namespace WeatherForecast.Controllers; namespace WeatherForecast.Controllers;
@ -21,18 +24,22 @@ public class TemplateController : ControllerBase {
private readonly IAuthorizationService _authorizationService; private readonly IAuthorizationService _authorizationService;
private readonly ITemplateBucketDataProvider _templateBucketDataProvider;
private readonly ITemplateService _templateService; private readonly ITemplateService _templateService;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="authorizationService"></param> /// <param name="authorizationService"></param>
/// <param name="templateBucketDataProvider"></param>
/// <param name="templateService"></param> /// <param name="templateService"></param>
public TemplateController( public TemplateController(
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
ITemplateBucketDataProvider templateBucketDataProvider,
ITemplateService templateService ITemplateService templateService
) { ) {
_authorizationService = authorizationService; _authorizationService = authorizationService;
_templateBucketDataProvider = templateBucketDataProvider;
_templateService = templateService; _templateService = templateService;
} }
@ -41,22 +48,34 @@ public class TemplateController : ControllerBase {
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <param name="file"></param> /// <param name="formFile"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("{siteId}")] [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(); return IDomainResult.Failed().ToActionResult();
using var ms = new MemoryStream(); 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);
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 result.ToActionResult();
} }
return Unauthorized();
}
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@ -64,8 +83,27 @@ public class TemplateController : ControllerBase {
/// <param name="fileId"></param> /// <param name="fileId"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet("{siteId}/{fileId}")] [HttpGet("{siteId}/{fileId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromRoute] Guid fileId) { public async Task<IActionResult> Get([FromRoute] Guid siteId, [FromRoute] Guid fileId) {
return BadRequest();
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> /// <summary>
@ -77,7 +115,7 @@ public class TemplateController : ControllerBase {
/// <param name="file"></param> /// <param name="file"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet("{siteId}/{fileId}")] [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(); return BadRequest();
} }

View File

@ -34,7 +34,7 @@ public class UtilsController : ControllerBase {
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("[action]")] [HttpPost("[action]")]
public IActionResult EncryptStringAes([FromBody] EncryptStringAesRequestModel requestData) { public IActionResult EncryptStringAes([FromBody] PostEncryptStringAesRequestModel requestData) {
var result = AesService.EncryptString(requestData.IV, requestData.Key, requestData.InputString); var result = AesService.EncryptString(requestData.IV, requestData.Key, requestData.InputString);
if(result != null) if(result != null)
return Ok(result); return Ok(result);
@ -42,5 +42,14 @@ public class UtilsController : ControllerBase {
return BadRequest(); 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> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpGet(Name = "GetWeatherForecast")] [HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecastResponseModel> Get() { public IEnumerable<GetWeatherForecastResponseModel> Get() {
return Enumerable.Range(1, 5).Select(index => new WeatherForecastResponseModel { return Enumerable.Range(1, 5).Select(index => new GetWeatherForecastResponseModel {
Date = DateTime.Now.AddDays(index), Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55), TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)] 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>
/// ///
/// </summary> /// </summary>
public List<CategoryItemResponseModel>? Categories { get; set; } public List<GetCategoryItemResponseModel>? Categories { get; set; }
/// <summary> /// <summary>
/// ///
@ -124,7 +124,7 @@ namespace WeatherForecast.Models.Abstractions.PostItem.Responses
/// <param name="categories"></param> /// <param name="categories"></param>
public PostItemResponseModelBase(PostItemBase<T> postItem, List<DomainObjects.Documents.Categories.Category> categories) : this(postItem) { public PostItemResponseModelBase(PostItemBase<T> postItem, List<DomainObjects.Documents.Categories.Category> categories) : this(postItem) {
L10n = postItem.L10n.Select(x => new PostItemL10nModel(x)).ToList(); 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(); MediaAttachemnts = postItem.MediaAttachments?.Select(x => new MediaAttachmentResponseModel(x)).ToList();
} }
@ -148,7 +148,7 @@ namespace WeatherForecast.Models.Abstractions.PostItem.Responses
Badges = postItemL10n.Badges; 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(); MediaAttachemnts = postItem.MediaAttachments?.Select(x => new MediaAttachmentResponseModel(x, locale)).ToList();
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public class PasswordResetRequestModel : RequestModelBase { public class PutPasswordResetRequestModel : RequestModelBase, IValidatableObject {
/// <summary> /// <summary>
/// ///
@ -29,7 +29,7 @@ namespace WeatherForecast.Models.Account.Requests {
/// </summary> /// </summary>
/// <param name="validationContext"></param> /// <param name="validationContext"></param>
/// <returns></returns> /// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Token)) if (string.IsNullOrWhiteSpace(Token))
yield return new ValidationResult($"{nameof(Token)} ${Errors.NullOrEmpty}"); 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>
/// ///
/// </summary> /// </summary>
public class BlogItemResponseModel : PostItemResponseModelBase<BlogDocument> { public class GetBlogItemResponseModel : PostItemResponseModelBase<BlogDocument> {
/// <summary> /// <summary>
/// ///
@ -26,7 +26,7 @@ namespace WeatherForecast.Models.Blog.Responses
/// </summary> /// </summary>
/// <param name="blogItem"></param> /// <param name="blogItem"></param>
/// <param name="categories"></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; ReadTime = blogItem.ReadTime;
Likes = blogItem.Likes; Likes = blogItem.Likes;
} }
@ -37,7 +37,7 @@ namespace WeatherForecast.Models.Blog.Responses
/// <param name="blogItem"></param> /// <param name="blogItem"></param>
/// <param name="categories"></param> /// <param name="categories"></param>
/// <param name="locale"></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; ReadTime = blogItem.ReadTime;
Likes = blogItem.Likes; Likes = blogItem.Likes;
} }

View File

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

View File

@ -12,7 +12,7 @@ namespace WeatherForecast.Models.Category.Requests
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public class CategoryL10nModel : RequestModelBase<CategoryL10n> { public class CategoryL10nModel : RequestModelBase, IValidatableObject {
/// <summary> /// <summary>
/// ///
@ -49,7 +49,7 @@ namespace WeatherForecast.Models.Category.Requests
/// <param name="validationContext"></param> /// <param name="validationContext"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="NotImplementedException"></exception> /// <exception cref="NotImplementedException"></exception>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(Locale)) if (string.IsNullOrWhiteSpace(Locale))
yield return new ValidationResult($"{nameof(Locale)} {Errors.NullOrWhiteSpace.Name}"); yield return new ValidationResult($"{nameof(Locale)} {Errors.NullOrWhiteSpace.Name}");
else if (Enumeration.FromDisplayName<Locales>(Locale) == null) 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>
/// ///
/// </summary> /// </summary>
public class CategoryItemRequestModel : RequestModelBase<DomainObjects.Documents.Categories.Category> { public class PostCategoryItemRequestModel : RequestModelBase, IValidatableObject {
/// <summary> /// <summary>
/// ///
@ -33,7 +33,7 @@ namespace WeatherForecast.Models.Category.Requests
/// </summary> /// </summary>
/// <param name="validationContext"></param> /// <param name="validationContext"></param>
/// <returns></returns> /// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (L10n.IsNullOrEmpty()) if (L10n.IsNullOrEmpty())
yield return new ValidationResult($"{nameof(L10n)} ${Errors.NullOrEmpty}"); 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>
/// ///
/// </summary> /// </summary>
public class CategoryItemResponseModel : ResponseModelBase { public class GetCategoryItemResponseModel : ResponseModelBase {
/// <summary> /// <summary>
/// ///
@ -39,7 +39,7 @@ namespace WeatherForecast.Models.Category.Responses
/// ///
/// </summary> /// </summary>
/// <param name="category"></param> /// <param name="category"></param>
public CategoryItemResponseModel(DomainObjects.Documents.Categories.Category category) { public GetCategoryItemResponseModel(DomainObjects.Documents.Categories.Category category) {
Id = category.Id; Id = category.Id;
SiteId = category.SiteId; SiteId = category.SiteId;
@ -51,7 +51,7 @@ namespace WeatherForecast.Models.Category.Responses
/// </summary> /// </summary>
/// <param name="category"></param> /// <param name="category"></param>
/// <param name="locale"></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; Id = category.Id;
SiteId = category.SiteId; 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>
/// ///
/// </summary> /// </summary>
public class ContentResponseModel : ResponseModelBase { public class GetContentResponseModel : ResponseModelBase {
/// <summary> /// <summary>
/// ///
@ -103,7 +103,7 @@ namespace WeatherForecast.Models.Content.Responses {
/// ///
/// </summary> /// </summary>
/// <param name="domainObject"></param> /// <param name="domainObject"></param>
public ContentResponseModel(ContentDocument domainObject) { public GetContentResponseModel(ContentDocument domainObject) {
SiteName = domainObject.SiteName; SiteName = domainObject.SiteName;
SiteUrl = domainObject.SiteUrl; SiteUrl = domainObject.SiteUrl;

View File

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

View File

@ -9,7 +9,7 @@ namespace WeatherForecast.Models.Initialization.Requests {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public class InitializeSystemRequestModel : RequestModelBase<InitializeSystemRequestModel> { public class PostInitializeSystemRequestModel : RequestModelBase, IValidatableObject {
/// <summary> /// <summary>
/// ///
@ -49,7 +49,7 @@ namespace WeatherForecast.Models.Initialization.Requests {
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
/// <exception cref="NotImplementedException"></exception> /// <exception cref="NotImplementedException"></exception>
public InitializeSystemRequestModel ToDomainObject() { public PostInitializeSystemRequestModel ToDomainObject() {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -58,7 +58,7 @@ namespace WeatherForecast.Models.Initialization.Requests {
/// </summary> /// </summary>
/// <param name="validationContext"></param> /// <param name="validationContext"></param>
/// <returns></returns> /// <returns></returns>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrWhiteSpace(SiteName)) if (string.IsNullOrWhiteSpace(SiteName))
yield return new ValidationResult($"{nameof(SiteName)} ${Errors.NullOrEmpty}"); 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>
/// ///
/// </summary> /// </summary>
public class ShopItemResponseModel : PostItemResponseModelBase<ShopDocument> { public class GetShopItemResponseModel : PostItemResponseModelBase<ShopDocument> {
/// <summary> /// <summary>
/// ///
@ -41,7 +41,7 @@ namespace WeatherForecast.Models.Shop.Responses
/// </summary> /// </summary>
/// <param name="shopCatalogItem"></param> /// <param name="shopCatalogItem"></param>
/// <param name="categories"></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; Sku = shopCatalogItem.Sku;
Rating = shopCatalogItem.Rating; Rating = shopCatalogItem.Rating;
Price = shopCatalogItem.Price; Price = shopCatalogItem.Price;
@ -55,7 +55,7 @@ namespace WeatherForecast.Models.Shop.Responses
/// <param name="shopCatalogItem"></param> /// <param name="shopCatalogItem"></param>
/// <param name="categories"></param> /// <param name="categories"></param>
/// <param name="locale"></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; Sku = shopCatalogItem.Sku;
Rating = shopCatalogItem.Rating; Rating = shopCatalogItem.Rating;
Price = shopCatalogItem.Price; Price = shopCatalogItem.Price;

View File

@ -5,7 +5,7 @@ namespace WeatherForecast.Models.Shop.Responses {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public class ShopItemsResponseModel : PaginationModelBase<ShopItemResponseModel> { public class GetShopItemsResponseModel : PaginationModelBase<GetShopItemResponseModel> {
/// <summary> /// <summary>
/// ///
@ -13,7 +13,7 @@ namespace WeatherForecast.Models.Shop.Responses {
/// <param name="currentPage"></param> /// <param name="currentPage"></param>
/// <param name="totalPages"></param> /// <param name="totalPages"></param>
/// <param name="items"></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) { } : 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>
/// ///
/// </summary> /// </summary>
public class PostTemplateRequestModel : RequestModelBase { public class PostTemplateRequestModel : RequestModelBase, IValidatableObject {
/// <summary> /// <summary>
/// ///
@ -24,7 +24,7 @@ namespace WeatherForecast.Models.Template.Requests {
/// <param name="validationContext"></param> /// <param name="validationContext"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="NotImplementedException"></exception> /// <exception cref="NotImplementedException"></exception>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (TemplateType == TemplateTypes.Unknown) if (TemplateType == TemplateTypes.Unknown)
yield return new ValidationResult($"{Errors.UnableToParse.Name} {nameof(TemplateType)}"); 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>
/// ///
/// </summary> /// </summary>
public class EncryptStringAesRequestModel : RequestModelBase { public class PostEncryptStringAesRequestModel : RequestModelBase, IValidatableObject {
/// <summary> /// <summary>
/// String to encrypt /// String to encrypt
@ -31,7 +31,7 @@ namespace WeatherForecast.Models.Utils.Requests {
/// <param name="validationContext"></param> /// <param name="validationContext"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="NotImplementedException"></exception> /// <exception cref="NotImplementedException"></exception>
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (string.IsNullOrEmpty(InputString)) if (string.IsNullOrEmpty(InputString))
yield return new ValidationResult($"{nameof(InputString)} {Errors.NullOrEmpty}"); yield return new ValidationResult($"{nameof(InputString)} {Errors.NullOrEmpty}");

View File

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

View File

@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Core.Enumerations;
using DataProviders.Collections; using DataProviders.Collections;
@ -44,32 +43,17 @@ public class BlogAuthorizationHandler : AuthorizationHandlerBase<BlogAuthorizati
var userRole = GetRole(site, user); var userRole = GetRole(site, user);
// Can only Admin, Editor, Author, Contributor (cannot set publish date) var req = requirement.Roles.SingleOrDefault(x => x.Role == userRole);
if (requirement.Action == CrudActions.Create if (req == null)
&& (userRole != Roles.Admin
&& userRole != Roles.Editor
&& userRole != Roles.Author
&& userRole != Roles.Contributor
&& (userRole == Roles.Contributor && resource.Any(x => x.Published != null))))
return Task.CompletedTask; return Task.CompletedTask;
// Can only Admin, Editor, Author, Contributor foreach (var res in resource) {
if (requirement.Action == CrudActions.Read if (req.OwnOnly && res.Author != user.Id)
&& (userRole != Roles.Admin
&& userRole != Roles.Editor
&& userRole != Roles.Author
&& userRole != Roles.Contributor))
return Task.CompletedTask; return Task.CompletedTask;
// Can only Admin, Editor, Author (own), Contributor (own, not yet pubblished) if (req.DenyPublished && res.Published != null)
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; return Task.CompletedTask;
}
context.Succeed(requirement); context.Succeed(requirement);
@ -80,5 +64,28 @@ public class BlogAuthorizationHandler : AuthorizationHandlerBase<BlogAuthorizati
/// <summary> /// <summary>
/// ///
/// </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); var userRole = GetRole(site, user);
// Can Admin, Editor, Shop manager var req = requirement.Roles.SingleOrDefault(x => x.Role == userRole);
if ((requirement.Action == CrudActions.Create || requirement.Action == CrudActions.Update) if (req == null)
&& (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)
return Task.CompletedTask; return Task.CompletedTask;
context.Succeed(requirement); context.Succeed(requirement);
@ -71,4 +54,14 @@ public class CategoryAuthorizationHandler : AuthorizationHandlerBase<CategoryAut
/// <summary> /// <summary>
/// ///
/// </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); var userRole = GetRole(site, user);
// Can Admin, Shop manager var req = requirement.Roles.SingleOrDefault(x => x.Role == userRole);
if (requirement.Action == CrudActions.Create if (req == null)
&& userRole != Roles.Admin
&& userRole != Roles.ShopManager)
return Task.CompletedTask; 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); context.Succeed(requirement);
return Task.CompletedTask; return Task.CompletedTask;
@ -77,5 +56,23 @@ namespace WeatherForecast.Policies
/// <summary> /// <summary>
/// ///
/// </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> /// </summary>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
(string?, IDomainResult) Authenticate(AuthenticationRequestModel requestData); (string?, IDomainResult) Authenticate(PostAuthenticationRequestModel requestData);
/// <summary> /// <summary>
/// ///
@ -29,7 +29,7 @@ namespace WeatherForecast.Services {
/// <param name="hostName"></param> /// <param name="hostName"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
IDomainResult PasswordRecovery(string hostName, PasswordRecoveryRequestModel requestData); IDomainResult PasswordRecovery(string hostName, PutPasswordRecoveryRequestModel requestData);
/// <summary> /// <summary>
@ -37,7 +37,7 @@ namespace WeatherForecast.Services {
/// </summary> /// </summary>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
IDomainResult PasswordReset(PasswordResetRequestModel requestData); IDomainResult PasswordReset(PutPasswordResetRequestModel requestData);
/// <summary> /// <summary>
@ -46,7 +46,7 @@ namespace WeatherForecast.Services {
/// <param name="user"></param> /// <param name="user"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
(Guid?, IDomainResult) PasswordChange(User user, PasswordChangeRequestModel requestData); (Guid?, IDomainResult) PasswordChange(User user, PutPasswordChangeRequestModel requestData);
} }
/// <summary> /// <summary>
@ -110,7 +110,7 @@ namespace WeatherForecast.Services {
/// </summary> /// </summary>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
public (string?, IDomainResult) Authenticate(AuthenticationRequestModel requestData) { public (string?, IDomainResult) Authenticate(PostAuthenticationRequestModel requestData) {
// Retrieve user from database by userName // Retrieve user from database by userName
var (user, getUserResult) = _userDataProvider.GetByUsername(requestData.Username); var (user, getUserResult) = _userDataProvider.GetByUsername(requestData.Username);
@ -137,7 +137,7 @@ namespace WeatherForecast.Services {
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="NotImplementedException"></exception> /// <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); var (user, getUserResult) = _userDataProvider.GetByUsername(requestData.Username);
if (!getUserResult.IsSuccess || user == null) if (!getUserResult.IsSuccess || user == null)
return getUserResult; return getUserResult;
@ -197,7 +197,7 @@ namespace WeatherForecast.Services {
/// </summary> /// </summary>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
public IDomainResult PasswordReset(PasswordResetRequestModel requestData) { public IDomainResult PasswordReset(PutPasswordResetRequestModel requestData) {
var (user, getUserResult) = _userDataProvider.GetByRecoveryToken(requestData.Token); var (user, getUserResult) = _userDataProvider.GetByRecoveryToken(requestData.Token);
if (!getUserResult.IsSuccess || user == null) if (!getUserResult.IsSuccess || user == null)
@ -216,7 +216,7 @@ namespace WeatherForecast.Services {
/// <param name="user"></param> /// <param name="user"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <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); 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.Responses;
using WeatherForecast.Models.Blog.Requests; using WeatherForecast.Models.Blog.Requests;
using DomainObjects.Documents.Posts; using DomainObjects.Documents.Posts;
using WeatherForecast.Models.BlogItem.Requests;
namespace WeatherForecast.Services namespace WeatherForecast.Services
{ {
@ -27,15 +28,15 @@ namespace WeatherForecast.Services
/// </summary> /// </summary>
/// <param name="blogItem"></param> /// <param name="blogItem"></param>
/// <returns></returns> /// <returns></returns>
(BlogItemResponseModel?, IDomainResult) Get(BlogDocument blogItem); (GetBlogItemResponseModel?, IDomainResult) Get(BlogDocument blogItem);
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="slug"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
(BlogItemResponseModel?, IDomainResult) GetSlug(Guid siteId, string slug); (GetBlogItemResponseModel?, IDomainResult) GetSlug(Guid siteId, GetBlogItemSlugRequestModel requestData);
/// <summary> /// <summary>
/// ///
@ -43,7 +44,7 @@ namespace WeatherForecast.Services
/// <param name="blogItem"></param> /// <param name="blogItem"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
(Guid?, IDomainResult) Update(BlogDocument blogItem, BlogItemRequestModel requestData); (Guid?, IDomainResult) Update(BlogDocument blogItem, PutBlogItemRequestModel requestData);
} }
/// <summary> /// <summary>
@ -97,13 +98,13 @@ namespace WeatherForecast.Services
/// </summary> /// </summary>
/// <param name="item"></param> /// <param name="item"></param>
/// <returns></returns> /// <returns></returns>
public (BlogItemResponseModel?, IDomainResult) Get(BlogDocument item) { public (GetBlogItemResponseModel?, IDomainResult) Get(BlogDocument item) {
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(item.SiteId, item.Categories); var (categories, getCategoryResult) = _categoryDataProvider.GetMany(item.SiteId, item.Categories);
if (!getCategoryResult.IsSuccess || categories == null) 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> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="slug"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <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) if (!getBlogItemResult.IsSuccess || blog == null)
return IDomainResult.Failed<BlogItemResponseModel?>(); return IDomainResult.Failed<GetBlogItemResponseModel?>();
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(blog.SiteId, blog.Categories); var (categories, getCategoryResult) = _categoryDataProvider.GetMany(blog.SiteId, blog.Categories);
if (!getCategoryResult.IsSuccess || categories == null) 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> /// <summary>
@ -134,7 +135,7 @@ namespace WeatherForecast.Services
/// <param name="blogItem"></param> /// <param name="blogItem"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
public (Guid?, IDomainResult) Update(BlogDocument blogItem, BlogItemRequestModel requestData) { public (Guid?, IDomainResult) Update(BlogDocument blogItem, PutBlogItemRequestModel requestData) {
// construct domain object from model // construct domain object from model
var newItem = requestData.ToDomainObject(blogItem.Author, blogItem.SiteId); var newItem = requestData.ToDomainObject(blogItem.Author, blogItem.SiteId);

View File

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

View File

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

View File

@ -5,9 +5,10 @@ using DataProviders.Collections;
using Core.Abstractions; using Core.Abstractions;
using Core.Enumerations; using Core.Enumerations;
using WeatherForecast.Models.Responses;
using WeatherForecast.Models.Category.Responses; using WeatherForecast.Models.Category.Responses;
using DomainObjects.Enumerations; using DomainObjects.Enumerations;
using WeatherForecast.Models.CategoryItem.Requests;
namespace WeatherForecast.Services { namespace WeatherForecast.Services {
@ -20,9 +21,9 @@ namespace WeatherForecast.Services {
/// ///
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="locale"></param> /// <param name="requestDat"></param>
/// <returns></returns> /// <returns></returns>
(List<CategoryItemResponseModel>?, IDomainResult) Get(Guid siteId, string? locale); (List<GetCategoryItemResponseModel>?, IDomainResult) Get(Guid siteId, GetCategoryItemsRequestModel requestData);
/// <summary> /// <summary>
/// ///
@ -57,21 +58,17 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="locale"></param> /// <param name="locale"></param>
/// <returns></returns> /// <returns></returns>
public (List<CategoryItemResponseModel>?, IDomainResult) Get(Guid siteId, string? locale) { public (List<GetCategoryItemResponseModel>?, IDomainResult) Get(Guid siteId, GetCategoryItemsRequestModel requestData) {
try { try {
var (items, result) = _categoryDataProvider.GetAll(siteId); var (items, result) = _categoryDataProvider.GetAll(siteId);
if (!result.IsSuccess || items == null) if (!result.IsSuccess || items == null)
return (null, result); return (null, result);
if (locale != null) { return IDomainResult.Success(items.Select(x => new GetCategoryItemResponseModel(x, requestData.Locale)).ToList());
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());
} }
catch (Exception ex) { catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception"); _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 DataProviders.Collections;
using WeatherForecast.Models.Responses;
using Core.Abstractions; using Core.Abstractions;
using WeatherForecast.Models.Content.Responses; using WeatherForecast.Models.Content.Responses;
using WeatherForecast.Models.Content.Requests;
namespace WeatherForecast.Services { namespace WeatherForecast.Services {
@ -19,7 +19,7 @@ namespace WeatherForecast.Services {
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="locale"></param> /// <param name="locale"></param>
/// <returns></returns> /// <returns></returns>
(ContentResponseModel?, IDomainResult) GetContent(Guid siteId, string locale); (GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, GetContentRequestModel requestData);
} }
/// <summary> /// <summary>
@ -45,19 +45,19 @@ namespace WeatherForecast.Services {
/// ///
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="locale"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
public (ContentResponseModel?, IDomainResult) GetContent(Guid siteId, string locale) { public (GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, GetContentRequestModel requestData) {
try { try {
var (content, result) = _contentDataProvider.Get(siteId); var (content, result) = _contentDataProvider.Get(siteId);
if (!result.IsSuccess || content == null) if (!result.IsSuccess || content == null)
return (null, result); 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) { catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception"); _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;
using ImageProvider.Fonts; using ImageProvider.Fonts;
using Core.Abstractions; 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 { namespace WeatherForecast.Services {
@ -16,6 +18,30 @@ namespace WeatherForecast.Services {
/// ///
/// </summary> /// </summary>
public interface IImageService { 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>
/// ///
/// </summary> /// </summary>
@ -24,7 +50,29 @@ namespace WeatherForecast.Services {
/// <param name="height"></param> /// <param name="height"></param>
/// <param name="imageId"></param> /// <param name="imageId"></param>
/// <returns></returns> /// <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> /// <summary>
@ -54,40 +102,107 @@ namespace WeatherForecast.Services {
_contentDataProvider = contentDataProvider; _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>
/// ///
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="width"></param> /// <param name="width"></param>
/// <param name="height"></param> /// <param name="height"></param>
/// <param name="imageId"></param> /// <param name="fileId"></param>
/// <returns></returns> /// <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 { try {
var (file, downloadResult) = _imageBucketDataProvider.Download(siteId, imageId); var (file, downloadResult) = _imageBucketDataProvider.Download(siteId, fileId);
if (!downloadResult.IsSuccess || file == null) if (!downloadResult.IsSuccess || file == null)
return IDomainResult.Failed<FileResponseModel?> (); return IDomainResult.Failed<GetImageResponseModel?>();
var (content, getContentResult) = _contentDataProvider.Get(siteId); var (content, getContentResult) = _contentDataProvider.Get(siteId);
if (!getContentResult.IsSuccess || content == null) 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); var (image, transformResult) = _imageProvider.ResizeAndWatermark(file.Bytes, width, height, FontsEnum.Montserrat, FontStylesEnum.Regular, content.First().SiteName);
if (!transformResult.IsSuccess || image == null) 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, Name = file.Name,
Bytes = image, Bytes = image,
ContentType = "image/jpeg" }); ContentType = "image/jpeg" });
} }
catch (Exception ex) { catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception"); _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> /// </summary>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
IDomainResult InitializeSystem(InitializeSystemRequestModel requestData); IDomainResult InitializeSystem(PostInitializeSystemRequestModel requestData);
} }
@ -79,7 +79,7 @@ public class InitializationService : ServiceBase<InitializationService>, IInitia
/// </summary> /// </summary>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
public IDomainResult InitializeSystem(InitializeSystemRequestModel requestData) { public IDomainResult InitializeSystem(PostInitializeSystemRequestModel requestData) {
var userId = "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60".ToGuid(); var userId = "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60".ToGuid();
var siteId = "404c8232-9048-4519-bfba-6e78dc7005ca".ToGuid(); var siteId = "404c8232-9048-4519-bfba-6e78dc7005ca".ToGuid();

View File

@ -3,11 +3,10 @@
using DataProviders.Collections; using DataProviders.Collections;
using Core.Abstractions; using Core.Abstractions;
using WeatherForecast.Models.Responses;
using WeatherForecast.Models.Shop.Requests;
using DomainObjects.Documents; using DomainObjects.Documents;
using DomainObjects.Enumerations; using DomainObjects.Enumerations;
using WeatherForecast.Models.ShopCart.Requests;
using WeatherForecast.Models.ShopCart.Responses;
namespace WeatherForecast.Services; namespace WeatherForecast.Services;
@ -24,7 +23,7 @@ public interface IShopCartItemService {
/// <param name="sku"></param> /// <param name="sku"></param>
/// <param name="requestModel"></param> /// <param name="requestModel"></param>
/// <returns></returns> /// <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>
/// ///
@ -32,7 +31,7 @@ public interface IShopCartItemService {
/// <param name="cartItem"></param> /// <param name="cartItem"></param>
/// <param name="locale"></param> /// <param name="locale"></param>
/// <returns></returns> /// <returns></returns>
(ShopCartItemResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, string? locale); (GetShopCartItemResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, GetShopCartItemRequestModel requestData);
/// <summary> /// <summary>
/// ///
@ -40,7 +39,7 @@ public interface IShopCartItemService {
/// <param name="cartItem"></param> /// <param name="cartItem"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
(Guid?, IDomainResult) Update(ShopCartDocument cartItem, ShopCartItemRequestModel requestData); (Guid?, IDomainResult) Update(ShopCartDocument cartItem, PutShopCartItemRequestModel requestData);
} }
/// <summary> /// <summary>
@ -74,7 +73,7 @@ public class ShopCartItemService : ServiceBase<ShopCartItemService>, IShopCartIt
/// <param name="sku"></param> /// <param name="sku"></param>
/// <param name="requestModel"></param> /// <param name="requestModel"></param>
/// <returns></returns> /// <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); var (_, getResult) = _shopCartDataProvider.Get(siteId, userId, sku);
if (getResult.IsSuccess) if (getResult.IsSuccess)
@ -95,11 +94,9 @@ public class ShopCartItemService : ServiceBase<ShopCartItemService>, IShopCartIt
/// ///
/// </summary> /// </summary>
/// <param name="cartItem"></param> /// <param name="cartItem"></param>
/// <param name="locale"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
public (ShopCartItemResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, string? locale) { public (GetShopCartItemResponseModel?, IDomainResult) Get(ShopCartDocument cartItem, GetShopCartItemRequestModel requestData) {
var (item, result) = _shopCatalogDataProvider.Get(cartItem.SiteId, cartItem.Sku); var (item, result) = _shopCatalogDataProvider.Get(cartItem.SiteId, cartItem.Sku);
if (!result.IsSuccess || item == null) { if (!result.IsSuccess || item == null) {
@ -107,11 +104,10 @@ public class ShopCartItemService : ServiceBase<ShopCartItemService>, IShopCartIt
if (!delteResult.IsSuccess) if (!delteResult.IsSuccess)
return (null, delteResult); return (null, delteResult);
return IDomainResult.NotFound<ShopCartItemResponseModel?>(); return IDomainResult.NotFound<GetShopCartItemResponseModel?>();
} }
else else
return IDomainResult.Success(new ShopCartItemResponseModel(item, cartItem, Enumeration.FromDisplayName<Locales>(locale ?? "en-US"))); return IDomainResult.Success(new GetShopCartItemResponseModel(item, cartItem, requestData.Locale));
} }
/// <summary> /// <summary>
@ -120,7 +116,7 @@ public class ShopCartItemService : ServiceBase<ShopCartItemService>, IShopCartIt
/// <param name="cartItem"></param> /// <param name="cartItem"></param>
/// <param name="requestData"></param> /// <param name="requestData"></param>
/// <returns></returns> /// <returns></returns>
public (Guid?, IDomainResult) Update(ShopCartDocument cartItem, ShopCartItemRequestModel requestData) { public (Guid?, IDomainResult) Update(ShopCartDocument cartItem, PutShopCartItemRequestModel requestData) {
// construct domain object from model // construct domain object from model
var newItem = requestData.ToDomainObject(cartItem.Sku, cartItem.UserId, cartItem.SiteId); var newItem = requestData.ToDomainObject(cartItem.Sku, cartItem.UserId, cartItem.SiteId);

View File

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

View File

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

View File

@ -6,9 +6,10 @@ using Core.Abstractions;
using Core.Enumerations; using Core.Enumerations;
using WeatherForecast.Models; using WeatherForecast.Models;
using WeatherForecast.Models.Responses;
using WeatherForecast.Models.Shop.Responses; using WeatherForecast.Models.Shop.Responses;
using DomainObjects.Enumerations; using DomainObjects.Enumerations;
using WeatherForecast.Models.Shop.Requests;
namespace WeatherForecast.Services { namespace WeatherForecast.Services {
@ -27,7 +28,7 @@ namespace WeatherForecast.Services {
/// <param name="locale"></param> /// <param name="locale"></param>
/// <param name="searchText"></param> /// <param name="searchText"></param>
/// <returns></returns> /// <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> /// <summary>
/// ///
@ -64,40 +65,32 @@ namespace WeatherForecast.Services {
/// ///
/// </summary> /// </summary>
/// <param name="siteId"></param> /// <param name="siteId"></param>
/// <param name="category"></param> /// <param name="requestData"></param>
/// <param name="currentPage"></param>
/// <param name="itemsPerPage"></param>
/// <param name="locale"></param>
/// <param name="searchText"></param>
/// <returns></returns> /// <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 { 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) if (!result.IsSuccess || items == null)
return (null, result); return (null, result);
var shopItems = new List<GetShopItemResponseModel>();
var shopItems = new List<ShopItemResponseModel>();
foreach (var item in items) { foreach (var item in items) {
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories); var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories);
if (!getCategoryResult.IsSuccess || categories == null) if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<ShopItemsResponseModel?>(); return IDomainResult.Failed<GetShopItemsResponseModel?>();
if (locale != null) shopItems.Add(new GetShopItemResponseModel(item, categories, requestData.Locale));
shopItems.Add(new ShopItemResponseModel(item, categories, Enumeration.FromDisplayName<Locales>(locale) ?? Locales.Us));
else
shopItems.Add(new ShopItemResponseModel(item, categories));
} }
return shopItems.Count > 0 return shopItems.Count > 0
? IDomainResult.Success(new ShopItemsResponseModel(currentPage, 0, shopItems)) ? IDomainResult.Success(new GetShopItemsResponseModel(requestData.CurrentPage, 0, shopItems))
: IDomainResult.NotFound<ShopItemsResponseModel?>(); : IDomainResult.NotFound<GetShopItemsResponseModel?>();
} }
catch (Exception ex) { catch (Exception ex) {
_logger.LogError(ex, "Unhandled exception"); _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>
/// ///
/// </summary> /// </summary>
/// <param name="requestData"></param>
/// <param name="file"></param> /// <param name="file"></param>
/// <returns></returns> /// <returns></returns>
(Guid?, IDomainResult) Post(PostTemplateRequestModel requestData, BucketFile file); (Guid?, IDomainResult) Post(BucketFile file);
/// <summary> /// <summary>
/// ///
@ -53,10 +52,9 @@ public class TemplateService : ServiceBase<TemplateService>, ITemplateService {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="requestData"></param>
/// <param name="file"></param> /// <param name="file"></param>
/// <returns></returns> /// <returns></returns>
public (Guid?, IDomainResult) Post(PostTemplateRequestModel requestData, BucketFile file) { public (Guid?, IDomainResult) Post(BucketFile file) {
var (fileId, uploadFileResult) = _templateBucketDataProvider.Upload(file); var (fileId, uploadFileResult) = _templateBucketDataProvider.Upload(file);
if (!uploadFileResult.IsSuccess || fileId == null) if (!uploadFileResult.IsSuccess || fileId == null)

View File

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

View File

@ -3,4 +3,4 @@ WiredTiger 10.0.2: (December 21, 2021)
WiredTiger version WiredTiger version
major=10,minor=0,patch=2 major=10,minor=0,patch=2
file:WiredTiger.wt 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