Refactoring, database structure changed
This commit is contained in:
15
WatchIt.DTO/Converters/ColorJsonConverter.cs
Normal file
15
WatchIt.DTO/Converters/ColorJsonConverter.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Drawing;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace WatchIt.DTO.Converters;
|
||||
|
||||
public class ColorJsonConverter : JsonConverter<Color>
|
||||
{
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public override Color Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => ColorTranslator.FromHtml(reader.GetString());
|
||||
public override void Write(Utf8JsonWriter writer, Color value, JsonSerializerOptions options) => writer.WriteStringValue("#" + value.R.ToString("X2") + value.G.ToString("X2") + value.B.ToString("X2"));
|
||||
|
||||
#endregion
|
||||
}
|
||||
11
WatchIt.DTO/CustomValidators.cs
Normal file
11
WatchIt.DTO/CustomValidators.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace WatchIt.DTO;
|
||||
|
||||
public static class CustomValidators
|
||||
{
|
||||
public static IRuleBuilderOptions<T, TProperty> CannotBeIn<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, IEnumerable<TProperty> collection) => ruleBuilder.Must(x => !collection.Any(e => Equals(e, x)));
|
||||
public static IRuleBuilderOptions<T, TProperty> CannotBeIn<T, TProperty, TCollectionType>(this IRuleBuilder<T, TProperty> ruleBuilder, IEnumerable<TCollectionType> collection, Func<TCollectionType, TProperty> propertyFunc) => ruleBuilder.Must(x => !collection.Select(propertyFunc).Any(e => Equals(e, x)));
|
||||
public static IRuleBuilderOptions<T, TProperty> MustBeIn<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, IEnumerable<TProperty> collection) => ruleBuilder.Must(x => collection.Any(e => Equals(e, x)));
|
||||
public static IRuleBuilderOptions<T, TProperty> MustBeIn<T, TProperty, TCollectionType>(this IRuleBuilder<T, TProperty> ruleBuilder, IEnumerable<TCollectionType> collection, Func<TCollectionType, TProperty> propertyFunc) => ruleBuilder.Must(x => collection.Select(propertyFunc).Any(e => Equals(e, x)));
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using WatchIt.DTO.Models.Controllers.Accounts.Account.Filters;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account;
|
||||
|
||||
public class AccountFilterQuery : IFilterQuery<Database.Model.Accounts.Account>
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
[FromQuery(Name = "username")]
|
||||
public string? Username { get; set; }
|
||||
|
||||
[FromQuery(Name = "email")]
|
||||
public string? Email { get; set; }
|
||||
|
||||
[FromQuery(Name = "is_admin")]
|
||||
public bool? IsAdmin { get; set; }
|
||||
|
||||
[FromQuery(Name = "active_date_from")]
|
||||
public DateOnly? ActiveDateFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "active_date_to")]
|
||||
public DateOnly? ActiveDateTo { get; set; }
|
||||
|
||||
[FromQuery(Name = "join_date_from")]
|
||||
public DateOnly? JoinDateFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "join_date_to")]
|
||||
public DateOnly? JoinDateTo { get; set; }
|
||||
|
||||
[FromQuery(Name = "description")]
|
||||
public string? Description { get; set; }
|
||||
|
||||
[FromQuery(Name = "gender_id")]
|
||||
public short? GenderId { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public IEnumerable<Filter<Database.Model.Accounts.Account>> GetFilters() =>
|
||||
[
|
||||
new AccountUsernameFilter(Username),
|
||||
new AccountEmailFilter(Email),
|
||||
new AccountIsAdminFilter(IsAdmin),
|
||||
new AccountActiveDateFromFilter(ActiveDateFrom),
|
||||
new AccountActiveDateToFilter(ActiveDateTo),
|
||||
new AccountJoinDateFromFilter(JoinDateFrom),
|
||||
new AccountJoinDateToFilter(JoinDateTo),
|
||||
new AccountDescriptionFilter(Description),
|
||||
new AccountGenderIdFilter(GenderId),
|
||||
];
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account;
|
||||
|
||||
public static class AccountOrderKeys
|
||||
{
|
||||
public static readonly Dictionary<string, Expression<Func<Database.Model.Accounts.Account, object?>>> Base = new Dictionary<string, Expression<Func<Database.Model.Accounts.Account, object?>>>
|
||||
{
|
||||
{ "id", x => x.Id },
|
||||
{ "username", x => x.Username },
|
||||
{ "email", x => x.Email },
|
||||
{ "is_admin", x => x.IsAdmin },
|
||||
{ "active_date", x => x.ActiveDate },
|
||||
{ "join_date", x => x.JoinDate },
|
||||
{ "description", x => x.Description },
|
||||
{ "gender", x => x.Gender != null ? x.Gender.Name : null },
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account;
|
||||
|
||||
public class AccountRequest : IPasswordEditRequest
|
||||
{
|
||||
public string Username { get; set; } = null!;
|
||||
public string Email { get; set; } = null!;
|
||||
public string Password { get; set; } = null!;
|
||||
public string PasswordConfirmation { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using FluentValidation;
|
||||
using WatchIt.Database;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account;
|
||||
|
||||
public class AccountRequestValidator : AbstractValidator<AccountRequest>
|
||||
{
|
||||
public AccountRequestValidator(DatabaseContext database)
|
||||
{
|
||||
Include(new PasswordEditRequestValidator());
|
||||
RuleFor(x => x.Username).MinimumLength(5)
|
||||
.MaximumLength(50)
|
||||
.CannotBeIn(database.Accounts, x => x.Username).WithMessage("Username was already used");
|
||||
RuleFor(x => x.Email).EmailAddress()
|
||||
.CannotBeIn(database.Accounts, x => x.Email).WithMessage("Email was already used");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using WatchIt.DTO.Models.Controllers.Genders.Gender;
|
||||
using WatchIt.DTO.Models.Generics.Image;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account;
|
||||
|
||||
public class AccountResponse
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string Username { get; set; } = null!;
|
||||
public string Email { get; set; } = null!;
|
||||
public bool IsAdmin { get; set; }
|
||||
public DateTimeOffset ActiveDate { get; set; }
|
||||
public DateTimeOffset JoinDate { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public GenderResponse? Gender { get; set; }
|
||||
public ImageResponse? ProfilePicture { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account.Filters;
|
||||
|
||||
public record AccountActiveDateFromFilter : Filter<Database.Model.Accounts.Account>
|
||||
{
|
||||
public AccountActiveDateFromFilter(DateOnly? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.ActiveDate.UtcDateTime.CompareTo(query.Value) >= 0
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account.Filters;
|
||||
|
||||
public record AccountActiveDateToFilter : Filter<Database.Model.Accounts.Account>
|
||||
{
|
||||
public AccountActiveDateToFilter(DateOnly? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.ActiveDate.UtcDateTime.CompareTo(query.Value) <= 0
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account.Filters;
|
||||
|
||||
public record AccountDescriptionFilter : Filter<Database.Model.Accounts.Account>
|
||||
{
|
||||
public AccountDescriptionFilter(string? descriptionRegex) : base(x =>
|
||||
(
|
||||
string.IsNullOrWhiteSpace(descriptionRegex)
|
||||
||
|
||||
(
|
||||
!string.IsNullOrWhiteSpace(x.Description)
|
||||
&&
|
||||
Regex.IsMatch(x.Description, descriptionRegex, RegexOptions.IgnoreCase)
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account.Filters;
|
||||
|
||||
public record AccountEmailFilter : Filter<Database.Model.Accounts.Account>
|
||||
{
|
||||
public AccountEmailFilter(string? emailRegex) : base(x =>
|
||||
(
|
||||
string.IsNullOrWhiteSpace(emailRegex)
|
||||
||
|
||||
(
|
||||
!string.IsNullOrWhiteSpace(x.Username)
|
||||
&&
|
||||
Regex.IsMatch(x.Username, emailRegex, RegexOptions.IgnoreCase)
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account.Filters;
|
||||
|
||||
public record AccountGenderIdFilter : Filter<Database.Model.Accounts.Account>
|
||||
{
|
||||
public AccountGenderIdFilter(short? genderId) : base(x =>
|
||||
(
|
||||
genderId == null
|
||||
||
|
||||
x.GenderId == genderId
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account.Filters;
|
||||
|
||||
public record AccountIsAdminFilter : Filter<Database.Model.Accounts.Account>
|
||||
{
|
||||
public AccountIsAdminFilter(bool? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.IsAdmin == query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account.Filters;
|
||||
|
||||
public record AccountJoinDateFromFilter : Filter<Database.Model.Accounts.Account>
|
||||
{
|
||||
public AccountJoinDateFromFilter(DateOnly? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.JoinDate.UtcDateTime.CompareTo(query.Value) >= 0
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account.Filters;
|
||||
|
||||
public record AccountJoinDateToFilter : Filter<Database.Model.Accounts.Account>
|
||||
{
|
||||
public AccountJoinDateToFilter(DateOnly? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.JoinDate.UtcDateTime.CompareTo(query.Value) <= 0
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.Account.Filters;
|
||||
|
||||
public record AccountUsernameFilter : Filter<Database.Model.Accounts.Account>
|
||||
{
|
||||
public AccountUsernameFilter(string? usernameRegex) : base(x =>
|
||||
(
|
||||
string.IsNullOrWhiteSpace(usernameRegex)
|
||||
||
|
||||
(
|
||||
!string.IsNullOrWhiteSpace(x.Username)
|
||||
&&
|
||||
Regex.IsMatch(x.Username, usernameRegex, RegexOptions.IgnoreCase)
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountBackgroundPicture;
|
||||
|
||||
public class AccountBackgroundPictureRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public Guid Id { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using FluentValidation;
|
||||
using WatchIt.Database;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountBackgroundPicture;
|
||||
|
||||
public class AccountBackgroundPictureRequestValidator : AbstractValidator<AccountBackgroundPictureRequest>
|
||||
{
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public AccountBackgroundPictureRequestValidator(DatabaseContext database)
|
||||
{
|
||||
RuleFor(x => x.Id).MustBeIn(database.PhotoBackgrounds, x => x.Id).WithMessage("Background does not exists");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountEmail;
|
||||
|
||||
public class AccountEmailRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public string Email { get; set; } = null!;
|
||||
public string Password { get; set; } = null!;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using FluentValidation;
|
||||
using WatchIt.Database;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountEmail;
|
||||
|
||||
public class AccountEmailRequestValidator : AbstractValidator<AccountEmailRequest>
|
||||
{
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public AccountEmailRequestValidator(DatabaseContext database)
|
||||
{
|
||||
RuleFor(x => x.Email).EmailAddress()
|
||||
.CannotBeIn(database.Accounts, x => x.Email).WithMessage("Email is already used");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountLogout;
|
||||
|
||||
public class AccountLogoutRequest
|
||||
{
|
||||
public string? RefreshToken { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountPassword;
|
||||
|
||||
public class AccountPasswordRequest : IPasswordEditRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public string OldPassword { get; set; } = null!;
|
||||
public string Password { get; set; } = null!;
|
||||
public string PasswordConfirmation { get; set; } = null!;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountPassword;
|
||||
|
||||
public class AccountPasswordRequestValidator : AbstractValidator<AccountPasswordRequest>
|
||||
{
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public AccountPasswordRequestValidator()
|
||||
{
|
||||
Include(new PasswordEditRequestValidator());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountProfileInfo;
|
||||
|
||||
public class AccountProfileInfoRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public string? Description { get; set; }
|
||||
public short? GenderId { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using FluentValidation;
|
||||
using WatchIt.Database;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountProfileInfo;
|
||||
|
||||
public class AccountProfileInfoRequestValidator : AbstractValidator<AccountProfileInfoRequest>
|
||||
{
|
||||
public AccountProfileInfoRequestValidator(DatabaseContext database)
|
||||
{
|
||||
RuleFor(x => x.Description).MaximumLength(1000);
|
||||
When(x => x.GenderId.HasValue, () =>
|
||||
{
|
||||
RuleFor(x => x.GenderId!.Value).MustBeIn(database.Genders.Select(x => x.Id));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountUsername;
|
||||
|
||||
public class AccountUsernameRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public string Username { get; set; } = null!;
|
||||
public string Password { get; set; } = null!;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using FluentValidation;
|
||||
using WatchIt.Database;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts.AccountUsername;
|
||||
|
||||
public class AccountUsernameRequestValidator : AbstractValidator<AccountUsernameRequest>
|
||||
{
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public AccountUsernameRequestValidator(DatabaseContext database)
|
||||
{
|
||||
RuleFor(x => x.Username).MinimumLength(5)
|
||||
.MaximumLength(50)
|
||||
.CannotBeIn(database.Accounts, x => x.Username).WithMessage("Username is already used");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
163
WatchIt.DTO/Models/Controllers/Accounts/AccountsMappers.cs
Normal file
163
WatchIt.DTO/Models/Controllers/Accounts/AccountsMappers.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using WatchIt.Database.Model.Accounts;
|
||||
using WatchIt.DTO.Models.Controllers.Accounts.Account;
|
||||
using WatchIt.DTO.Models.Controllers.Accounts.AccountBackgroundPicture;
|
||||
using WatchIt.DTO.Models.Controllers.Accounts.AccountEmail;
|
||||
using WatchIt.DTO.Models.Controllers.Accounts.AccountPassword;
|
||||
using WatchIt.DTO.Models.Controllers.Accounts.AccountProfileInfo;
|
||||
using WatchIt.DTO.Models.Controllers.Accounts.AccountUsername;
|
||||
using WatchIt.DTO.Models.Controllers.Genders;
|
||||
using WatchIt.DTO.Models.Generics.Image;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts;
|
||||
|
||||
public static class AccountsMappers
|
||||
{
|
||||
#region PUBLIC METHODS
|
||||
|
||||
#region Account
|
||||
|
||||
public static Database.Model.Accounts.Account ToEntity(this AccountRequest request, Func<string, PasswordData> passwordGenFunc)
|
||||
{
|
||||
PasswordData generatedPassword = passwordGenFunc(request.Password);
|
||||
return new Database.Model.Accounts.Account
|
||||
{
|
||||
Username = request.Username,
|
||||
Email = request.Email,
|
||||
Password = generatedPassword.PasswordHash,
|
||||
LeftSalt = generatedPassword.LeftSalt,
|
||||
RightSalt = generatedPassword.RightSalt,
|
||||
};
|
||||
}
|
||||
|
||||
public static AccountResponse ToResponse(this Database.Model.Accounts.Account account) => new AccountResponse
|
||||
{
|
||||
Id = account.Id,
|
||||
Username = account.Username,
|
||||
Email = account.Email,
|
||||
IsAdmin = account.IsAdmin,
|
||||
JoinDate = account.JoinDate,
|
||||
ActiveDate = account.ActiveDate,
|
||||
Description = account.Description,
|
||||
Gender = account.Gender?.ToResponse(),
|
||||
ProfilePicture = account.ProfilePicture?.ToResponse(),
|
||||
};
|
||||
|
||||
public static void UpdateActiveDate(this Database.Model.Accounts.Account account)
|
||||
{
|
||||
account.ActiveDate = DateTimeOffset.UtcNow;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AccountUsername
|
||||
|
||||
public static void UpdateWithRequest(this Database.Model.Accounts.Account account, AccountUsernameRequest request)
|
||||
{
|
||||
account.Username = request.Username;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AccountEmail
|
||||
|
||||
public static void UpdateWithRequest(this Database.Model.Accounts.Account account, AccountEmailRequest request)
|
||||
{
|
||||
account.Email = request.Email;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AccountPassword
|
||||
|
||||
public static void UpdateWithRequest(this Database.Model.Accounts.Account account, AccountPasswordRequest request, Func<string, PasswordData> passwordGenFunc)
|
||||
{
|
||||
PasswordData generatedPassword = passwordGenFunc(request.Password);
|
||||
account.Password = generatedPassword.PasswordHash;
|
||||
account.LeftSalt = generatedPassword.LeftSalt;
|
||||
account.RightSalt = generatedPassword.RightSalt;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AccountProfileInfo
|
||||
|
||||
public static void UpdateWithRequest(this Database.Model.Accounts.Account account, AccountProfileInfoRequest request)
|
||||
{
|
||||
account.Description = request.Description;
|
||||
account.GenderId = request.GenderId;
|
||||
}
|
||||
|
||||
public static AccountProfileInfoRequest ToProfileInfoRequest(this AccountResponse response) => new AccountProfileInfoRequest
|
||||
{
|
||||
Description = response.Description,
|
||||
GenderId = response.Gender?.Id
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region AccountProfilePicture
|
||||
|
||||
public static AccountProfilePicture ToEntity(this ImageRequest request, long accountId) => new AccountProfilePicture
|
||||
{
|
||||
AccountId = accountId,
|
||||
Image = request.Image,
|
||||
MimeType = request.MimeType,
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region AccountBackgroundPicture
|
||||
|
||||
public static Database.Model.Accounts.AccountBackgroundPicture ToEntity(this AccountBackgroundPictureRequest request, long accountId) => new Database.Model.Accounts.AccountBackgroundPicture
|
||||
{
|
||||
AccountId = accountId,
|
||||
BackgroundId = request.Id,
|
||||
};
|
||||
|
||||
public static void UpdateWithRequest(this Database.Model.Accounts.AccountBackgroundPicture entity, AccountBackgroundPictureRequest request)
|
||||
{
|
||||
entity.BackgroundId = request.Id;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AccountRefreshToken
|
||||
|
||||
public static AccountRefreshToken CreateAccountRefreshTokenEntity(Guid token, long accountId, DateTimeOffset expirationDate, bool isExtendable) => new AccountRefreshToken
|
||||
{
|
||||
Token = token,
|
||||
AccountId = accountId,
|
||||
ExpirationDate = expirationDate,
|
||||
IsExtendable = isExtendable,
|
||||
};
|
||||
|
||||
public static void UpdateExpirationDate(this AccountRefreshToken entity, DateTimeOffset expirationDate)
|
||||
{
|
||||
entity.ExpirationDate = expirationDate;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AccountFollow
|
||||
|
||||
public static AccountFollow CreateAccountFollowEntity(long accountFollowerId, long accountFollowedId) => new AccountFollow
|
||||
{
|
||||
FollowerId = accountFollowerId,
|
||||
FollowedId = accountFollowedId,
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region PasswordData
|
||||
|
||||
public static PasswordData GetPasswordData(this Database.Model.Accounts.Account account) => new PasswordData
|
||||
{
|
||||
PasswordHash = account.Password,
|
||||
LeftSalt = account.LeftSalt,
|
||||
RightSalt = account.RightSalt,
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts;
|
||||
|
||||
public interface IPasswordEditRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
string Password { get; set; }
|
||||
string PasswordConfirmation { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
12
WatchIt.DTO/Models/Controllers/Accounts/PasswordData.cs
Normal file
12
WatchIt.DTO/Models/Controllers/Accounts/PasswordData.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts;
|
||||
|
||||
public struct PasswordData
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public required byte[] PasswordHash { get; set; }
|
||||
public required string LeftSalt { get; set; }
|
||||
public required string RightSalt { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Accounts;
|
||||
|
||||
public class PasswordEditRequestValidator : AbstractValidator<IPasswordEditRequest>
|
||||
{
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public PasswordEditRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.Password).NotNull()
|
||||
.NotEmpty();
|
||||
When(x => x.Password is not null, () =>
|
||||
{
|
||||
RuleFor(x => x.Password).MinimumLength(8)
|
||||
.Must(x => x.Any(char.IsUpper)).WithMessage("Password must contain at least one uppercase letter.")
|
||||
.Must(x => x.Any(char.IsLower)).WithMessage("Password must contain at least one lowercase letter.")
|
||||
.Must(x => x.Any(char.IsDigit)).WithMessage("Password must contain at least one digit.");
|
||||
});
|
||||
RuleFor(x => x.PasswordConfirmation).Equal(x => x.Password);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using WatchIt.Database.Model.Accounts;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Authentication;
|
||||
|
||||
public static class AuthenticationMappers
|
||||
{
|
||||
#region Authentication
|
||||
|
||||
public static AuthenticationResponse CreateAuthenticationResponse(string accessToken, string refreshToken) => new AuthenticationResponse
|
||||
{
|
||||
AccessToken = accessToken,
|
||||
RefreshToken = refreshToken,
|
||||
};
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Authentication;
|
||||
|
||||
public class AuthenticationRefreshRequest
|
||||
{
|
||||
public string AccessToken { get; set; } = null!;
|
||||
public string RefreshToken { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Authentication;
|
||||
|
||||
public class AuthenticationRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public string UsernameOrEmail { get; set; } = null!;
|
||||
public string Password { get; set; } = null!;
|
||||
public bool RememberMe { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Authentication;
|
||||
|
||||
public class AuthenticationRequestValidator : AbstractValidator<AuthenticationRequest>
|
||||
{
|
||||
public AuthenticationRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.UsernameOrEmail).NotEmpty();
|
||||
RuleFor(x => x.Password).NotEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Authentication;
|
||||
|
||||
public class AuthenticationResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public string AccessToken { get; init; } = null!;
|
||||
public string RefreshToken { get; init; } = null!;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Genders.Gender.Filters;
|
||||
|
||||
public record GenderNameFilter : Filter<Database.Model.Genders.Gender>
|
||||
{
|
||||
public GenderNameFilter(string? nameRegex) : base(x =>
|
||||
(
|
||||
string.IsNullOrWhiteSpace(nameRegex)
|
||||
||
|
||||
(
|
||||
!string.IsNullOrWhiteSpace(x.Name)
|
||||
&&
|
||||
Regex.IsMatch(x.Name, nameRegex, RegexOptions.IgnoreCase)
|
||||
)
|
||||
)) { }
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using WatchIt.DTO.Models.Controllers.Genders.Gender.Filters;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Genders.Gender;
|
||||
|
||||
public class GenderFilterQuery : IFilterQuery<Database.Model.Genders.Gender>
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
[FromQuery(Name = "name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public IEnumerable<Filter<Database.Model.Genders.Gender>> GetFilters() =>
|
||||
[
|
||||
new GenderNameFilter(Name),
|
||||
];
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Genders.Gender;
|
||||
|
||||
public static class GenderOrderKeys
|
||||
{
|
||||
public static readonly Dictionary<string, Expression<Func<Database.Model.Genders.Gender, object?>>> Base = new Dictionary<string, Expression<Func<Database.Model.Genders.Gender, object?>>>
|
||||
{
|
||||
{ "id", x => x.Id },
|
||||
{ "name", x => x.Name },
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Genders.Gender;
|
||||
|
||||
public class GenderRequest
|
||||
{
|
||||
public string Name { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Genders.Gender;
|
||||
|
||||
public class GenderRequestValidator : AbstractValidator<GenderRequest>
|
||||
{
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public GenderRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.Name).MaximumLength(100);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Genders.Gender;
|
||||
|
||||
public class GenderResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public short Id { get; set; }
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
#endregion
|
||||
}
|
||||
17
WatchIt.DTO/Models/Controllers/Genders/GendersMappers.cs
Normal file
17
WatchIt.DTO/Models/Controllers/Genders/GendersMappers.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using WatchIt.DTO.Models.Controllers.Genders.Gender;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Genders;
|
||||
|
||||
public static class GendersMappers
|
||||
{
|
||||
public static GenderResponse ToResponse(this Database.Model.Genders.Gender entity) => new GenderResponse
|
||||
{
|
||||
Id = entity.Id,
|
||||
Name = entity.Name,
|
||||
};
|
||||
|
||||
public static Database.Model.Genders.Gender ToEntity(this GenderRequest request) => new Database.Model.Genders.Gender
|
||||
{
|
||||
Name = request.Name,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Genres.Genre.Filters;
|
||||
|
||||
public record GenreNameFilter : Filter<Database.Model.Genres.Genre>
|
||||
{
|
||||
public GenreNameFilter(string? nameRegex) : base(x =>
|
||||
(
|
||||
string.IsNullOrWhiteSpace(nameRegex)
|
||||
||
|
||||
(
|
||||
!string.IsNullOrWhiteSpace(x.Name)
|
||||
&&
|
||||
Regex.IsMatch(x.Name, nameRegex, RegexOptions.IgnoreCase)
|
||||
)
|
||||
)) { }
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using WatchIt.DTO.Models.Controllers.Genres.Genre.Filters;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Genres.Genre;
|
||||
|
||||
public class GenreFilterQuery : IFilterQuery<Database.Model.Genres.Genre>
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
[FromQuery(Name = "name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public IEnumerable<Filter<Database.Model.Genres.Genre>> GetFilters() =>
|
||||
[
|
||||
new GenreNameFilter(Name),
|
||||
];
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Genres.Genre;
|
||||
|
||||
public static class GenreOrderKeys
|
||||
{
|
||||
public static readonly Dictionary<string, Expression<Func<Database.Model.Genres.Genre, object?>>> Base = new Dictionary<string, Expression<Func<Database.Model.Genres.Genre, object?>>>
|
||||
{
|
||||
{ "id", x => x.Id },
|
||||
{ "name", x => x.Name },
|
||||
};
|
||||
}
|
||||
10
WatchIt.DTO/Models/Controllers/Genres/Genre/GenreRequest.cs
Normal file
10
WatchIt.DTO/Models/Controllers/Genres/Genre/GenreRequest.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Genres.Genre;
|
||||
|
||||
public class GenreRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Genres.Genre;
|
||||
|
||||
public class GenreRequestValidator : AbstractValidator<GenreRequest>
|
||||
{
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public GenreRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.Name).MaximumLength(100);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
11
WatchIt.DTO/Models/Controllers/Genres/Genre/GenreResponse.cs
Normal file
11
WatchIt.DTO/Models/Controllers/Genres/Genre/GenreResponse.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Genres.Genre;
|
||||
|
||||
public class GenreResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public short Id { get; set; }
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
#endregion
|
||||
}
|
||||
21
WatchIt.DTO/Models/Controllers/Genres/GenresMappers.cs
Normal file
21
WatchIt.DTO/Models/Controllers/Genres/GenresMappers.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using WatchIt.DTO.Models.Controllers.Genres.Genre;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Genres;
|
||||
|
||||
public static class GenresMappers
|
||||
{
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public static GenreResponse ToResponse(this Database.Model.Genres.Genre entity) => new GenreResponse
|
||||
{
|
||||
Id = entity.Id,
|
||||
Name = entity.Name,
|
||||
};
|
||||
|
||||
public static Database.Model.Genres.Genre ToEntity(this GenreRequest request) => new Database.Model.Genres.Genre
|
||||
{
|
||||
Name = request.Name,
|
||||
};
|
||||
|
||||
#endregion
|
||||
}
|
||||
208
WatchIt.DTO/Models/Controllers/Media/MediaMappers.cs
Normal file
208
WatchIt.DTO/Models/Controllers/Media/MediaMappers.cs
Normal file
@@ -0,0 +1,208 @@
|
||||
using WatchIt.Database.Model.Media;
|
||||
using WatchIt.DTO.Models.Controllers.Genres;
|
||||
using WatchIt.DTO.Models.Controllers.Media.Medium.Request;
|
||||
using WatchIt.DTO.Models.Controllers.Media.Medium.Response;
|
||||
using WatchIt.DTO.Models.Generics.Image;
|
||||
using WatchIt.DTO.Models.Generics.Rating;
|
||||
using WatchIt.DTO.Models.Generics.ViewCount;
|
||||
using MediumType = WatchIt.Database.Model.Media.MediumType;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media;
|
||||
|
||||
public static class MediaMappers
|
||||
{
|
||||
#region PUBLIC METHODS
|
||||
|
||||
#region Medium
|
||||
|
||||
public static MediumMovie ToEntity(this MediumMovieRequest request)
|
||||
{
|
||||
MediumMovie medium = new MediumMovie();
|
||||
medium.UpdateWithRequest(request);
|
||||
return medium;
|
||||
}
|
||||
|
||||
public static void UpdateWithRequest(this MediumMovie entity, MediumMovieRequest request)
|
||||
{
|
||||
entity.SetMediumEntityProperties(request);
|
||||
entity.Budget = request.Budget;
|
||||
}
|
||||
|
||||
public static MediumSeries ToEntity(this MediumSeriesRequest request)
|
||||
{
|
||||
MediumSeries medium = new MediumSeries();
|
||||
medium.UpdateWithRequest(request);
|
||||
return medium;
|
||||
}
|
||||
|
||||
public static void UpdateWithRequest(this MediumSeries entity, MediumSeriesRequest request)
|
||||
{
|
||||
entity.SetMediumEntityProperties(request);
|
||||
entity.HasEnded = request.HasEnded;
|
||||
}
|
||||
|
||||
public static MediumResponse ToResponse(this Database.Model.Media.Medium entity)
|
||||
{
|
||||
MediumResponse response = new MediumResponse();
|
||||
response.SetMediumResponseProperties(entity);
|
||||
response.Type = entity.Type == MediumType.Movie ? Medium.Response.MediumResponseType.Movie : Medium.Response.MediumResponseType.Series;
|
||||
return response;
|
||||
}
|
||||
|
||||
public static MediumMovieResponse ToResponse(this MediumMovie entity)
|
||||
{
|
||||
MediumMovieResponse response = new MediumMovieResponse();
|
||||
response.SetMediumResponseProperties(entity);
|
||||
response.SetMediumMovieResponseProperties(entity);
|
||||
return response;
|
||||
}
|
||||
|
||||
public static MediumSeriesResponse ToResponse(this MediumSeries entity)
|
||||
{
|
||||
MediumSeriesResponse response = new MediumSeriesResponse();
|
||||
response.SetMediumResponseProperties(entity);
|
||||
response.SetMediumSeriesResponseProperties(entity);
|
||||
return response;
|
||||
}
|
||||
|
||||
public static MediumUserRatedResponse ToResponse(this Database.Model.Media.Medium entity, long accountId)
|
||||
{
|
||||
MediumUserRatedResponse response = new MediumUserRatedResponse();
|
||||
response.SetMediumResponseProperties(entity);
|
||||
response.SetMediumUserRatedResponseProperties(entity, accountId);
|
||||
return response;
|
||||
}
|
||||
|
||||
public static MediumMovieUserRatedResponse ToResponse(this MediumMovie entity, long accountId)
|
||||
{
|
||||
MediumMovieUserRatedResponse response = new MediumMovieUserRatedResponse();
|
||||
response.SetMediumResponseProperties(entity);
|
||||
response.SetMediumMovieResponseProperties(entity);
|
||||
response.SetMediumUserRatedResponseProperties(entity, accountId);
|
||||
return response;
|
||||
}
|
||||
|
||||
public static MediumSeriesUserRatedResponse ToResponse(this MediumSeries entity, long accountId)
|
||||
{
|
||||
MediumSeriesUserRatedResponse response = new MediumSeriesUserRatedResponse();
|
||||
response.SetMediumResponseProperties(entity);
|
||||
response.SetMediumSeriesResponseProperties(entity);
|
||||
response.SetMediumUserRatedResponseProperties(entity, accountId);
|
||||
return response;
|
||||
}
|
||||
|
||||
public static MediumRequest ToRequest(this BaseMediumResponse response)
|
||||
{
|
||||
MediumRequest request = response switch
|
||||
{
|
||||
MediumMovieResponse mediumMovieResponse => new MediumMovieRequest
|
||||
{
|
||||
Budget = mediumMovieResponse.Budget,
|
||||
},
|
||||
MediumSeriesResponse mediumSeriesResponse => new MediumSeriesRequest
|
||||
{
|
||||
HasEnded = mediumSeriesResponse.HasEnded,
|
||||
}
|
||||
};
|
||||
request.Title = response.Title;
|
||||
request.Description = response.Description;
|
||||
request.OriginalTitle = response.OriginalTitle;
|
||||
request.ReleaseDate = response.ReleaseDate;
|
||||
request.Duration = response.Duration;
|
||||
return request;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MediumPicture
|
||||
|
||||
public static MediumPicture ToEntity(this ImageRequest request, long mediumId) => new Database.Model.Media.MediumPicture
|
||||
{
|
||||
MediumId = mediumId,
|
||||
Image = request.Image,
|
||||
MimeType = request.MimeType,
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region MediumGenre
|
||||
|
||||
public static MediumGenre CreateMediumGenre(long mediumId, short genreId) => new MediumGenre
|
||||
{
|
||||
MediumId = mediumId,
|
||||
GenreId = genreId,
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region MediumRating
|
||||
|
||||
public static MediumRating ToEntity(this RatingRequest request, long mediumId, long userId)
|
||||
{
|
||||
MediumRating entity = new MediumRating
|
||||
{
|
||||
MediumId = mediumId,
|
||||
AccountId = userId
|
||||
};
|
||||
entity.UpdateWithRequest(request);
|
||||
return entity;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MediumViewCount
|
||||
|
||||
public static MediumViewCount CreateMediumViewCountEntity(long mediumId) => new MediumViewCount
|
||||
{
|
||||
MediumId = mediumId,
|
||||
ViewCount = 1,
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
private static void SetMediumEntityProperties(this Database.Model.Media.Medium entity, MediumRequest request)
|
||||
{
|
||||
entity.Title = request.Title;
|
||||
entity.OriginalTitle = request.OriginalTitle;
|
||||
entity.Description = request.Description;
|
||||
entity.Duration = request.Duration;
|
||||
entity.ReleaseDate = request.ReleaseDate;
|
||||
}
|
||||
|
||||
private static void SetMediumResponseProperties(this BaseMediumResponse response, Database.Model.Media.Medium entity)
|
||||
{
|
||||
response.Id = entity.Id;
|
||||
response.Title = entity.Title;
|
||||
response.OriginalTitle = entity.OriginalTitle;
|
||||
response.Description = entity.Description;
|
||||
response.ReleaseDate = entity.ReleaseDate;
|
||||
response.Duration = entity.Duration;
|
||||
response.Genres = entity.Genres.Select(x => x.ToResponse());
|
||||
response.Rating = entity.Ratings.ToOverallResponse();
|
||||
response.ViewCount = entity.ViewCounts.ToResponse();
|
||||
response.Picture = entity.Picture?.ToResponse();
|
||||
}
|
||||
|
||||
private static void SetMediumMovieResponseProperties(this MediumMovieResponse response, MediumMovie entity)
|
||||
{
|
||||
response.Budget = entity.Budget;
|
||||
}
|
||||
|
||||
private static void SetMediumSeriesResponseProperties(this MediumSeriesResponse response, MediumSeries entity)
|
||||
{
|
||||
response.HasEnded = entity.HasEnded;
|
||||
}
|
||||
|
||||
private static void SetMediumUserRatedResponseProperties(this IMediumUserRatedResponse response, Database.Model.Media.Medium entity, long accountId)
|
||||
{
|
||||
response.RatingUser = entity.Ratings.SingleOrDefault(x => x.AccountId == accountId)?.ToUserResponse();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumDescriptionFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumDescriptionFilter(string? descriptionRegex) : base(x =>
|
||||
(
|
||||
string.IsNullOrWhiteSpace(descriptionRegex)
|
||||
||
|
||||
(
|
||||
!string.IsNullOrWhiteSpace(x.Description)
|
||||
&&
|
||||
Regex.IsMatch(x.Description, descriptionRegex, RegexOptions.IgnoreCase)
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumGenresFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumGenresFilter(IEnumerable<short>? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
query.All(y => x.Genres.Select(z => z.Id).Contains(y))
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumMovieBudgetFromFilter : Filter<Database.Model.Media.MediumMovie>
|
||||
{
|
||||
public MediumMovieBudgetFromFilter(decimal? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.Budget >= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumMovieBudgetToFilter : Filter<Database.Model.Media.MediumMovie>
|
||||
{
|
||||
public MediumMovieBudgetToFilter(decimal? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.Budget <= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumOriginalTitleFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumOriginalTitleFilter(string? originalTitleRegex) : base(x =>
|
||||
(
|
||||
string.IsNullOrWhiteSpace(originalTitleRegex)
|
||||
||
|
||||
(
|
||||
!string.IsNullOrWhiteSpace(x.OriginalTitle)
|
||||
&&
|
||||
Regex.IsMatch(x.OriginalTitle, originalTitleRegex, RegexOptions.IgnoreCase)
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumRatingAverageFromFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumRatingAverageFromFilter(decimal? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
(
|
||||
x.Ratings.Any()
|
||||
&&
|
||||
(decimal)x.Ratings.Average(y => y.Rating) >= query
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumRatingAverageToFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumRatingAverageToFilter(decimal? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
(
|
||||
x.Ratings.Any()
|
||||
&&
|
||||
(decimal)x.Ratings.Average(y => y.Rating) <= query
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumRatingCountFromFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumRatingCountFromFilter(long? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.Ratings.Count() >= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumRatingCountToFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumRatingCountToFilter(long? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.Ratings.Count() <= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumRatingUserDateFromFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumRatingUserDateFromFilter(DateOnly? query, long accountId) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
(
|
||||
x.Ratings.Any(x => x.AccountId == accountId)
|
||||
&&
|
||||
x.Ratings.First(x => x.AccountId == accountId).Date >= query.Value.ToDateTime(new TimeOnly(0, 0))
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumRatingUserDateToFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumRatingUserDateToFilter(DateOnly? query, long accountId) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
(
|
||||
x.Ratings.Any(x => x.AccountId == accountId)
|
||||
&&
|
||||
x.Ratings.First(x => x.AccountId == accountId).Date <= query.Value.ToDateTime(new TimeOnly(23, 59))
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumRatingUserRatingFromFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumRatingUserRatingFromFilter(byte? query, long accountId) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
(
|
||||
x.Ratings.Any(x => x.AccountId == accountId)
|
||||
&&
|
||||
x.Ratings.First(x => x.AccountId == accountId).Rating >= query
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumRatingUserRatingToFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumRatingUserRatingToFilter(byte? query, long accountId) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
(
|
||||
x.Ratings.Any(x => x.AccountId == accountId)
|
||||
&&
|
||||
x.Ratings.First(x => x.AccountId == accountId).Rating <= query
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumReleaseDateFromFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumReleaseDateFromFilter(DateOnly? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
(
|
||||
x.ReleaseDate.HasValue
|
||||
&&
|
||||
x.ReleaseDate.Value.CompareTo(query.Value) >= 0
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumReleaseDateToFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumReleaseDateToFilter(DateOnly? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
(
|
||||
x.ReleaseDate.HasValue
|
||||
&&
|
||||
x.ReleaseDate.Value.CompareTo(query.Value) <= 0
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumSeriesHasEndedFilter : Filter<Database.Model.Media.MediumSeries>
|
||||
{
|
||||
public MediumSeriesHasEndedFilter(bool? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.HasEnded == query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumTitleFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumTitleFilter(string? titleRegex) : base(x =>
|
||||
(
|
||||
string.IsNullOrWhiteSpace(titleRegex)
|
||||
||
|
||||
(
|
||||
!string.IsNullOrWhiteSpace(x.Title)
|
||||
&&
|
||||
Regex.IsMatch(x.Title, titleRegex, RegexOptions.IgnoreCase)
|
||||
)
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using WatchIt.Database.Model.Media;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumTypeFilter : Filter<Database.Model.Media.Medium>
|
||||
{
|
||||
public MediumTypeFilter(MediumType? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.Type == query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumViewCountLast24HoursFromFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumViewCountLast24HoursFromFilter(long? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.ViewCounts
|
||||
.Where(y => y.Date >= DateOnly.FromDateTime(DateTime.Now.AddDays(-1)))
|
||||
.Sum(y => y.ViewCount) >= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumViewCountLast24HoursToFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumViewCountLast24HoursToFilter(long? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.ViewCounts
|
||||
.Where(y => y.Date >= DateOnly.FromDateTime(DateTime.Now.AddDays(-1)))
|
||||
.Sum(y => y.ViewCount) <= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumViewCountLastMonthFromFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumViewCountLastMonthFromFilter(long? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.ViewCounts
|
||||
.Where(y => y.Date >= DateOnly.FromDateTime(DateTime.Now.AddMonths(-1)))
|
||||
.Sum(y => y.ViewCount) >= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumViewCountLastMonthToFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumViewCountLastMonthToFilter(long? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.ViewCounts
|
||||
.Where(y => y.Date >= DateOnly.FromDateTime(DateTime.Now.AddMonths(-1)))
|
||||
.Sum(y => y.ViewCount) <= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumViewCountLastWeekFromFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumViewCountLastWeekFromFilter(long? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.ViewCounts
|
||||
.Where(y => y.Date >= DateOnly.FromDateTime(DateTime.Now.AddDays(-7)))
|
||||
.Sum(y => y.ViewCount) >= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumViewCountLastWeekToFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumViewCountLastWeekToFilter(long? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.ViewCounts
|
||||
.Where(y => y.Date >= DateOnly.FromDateTime(DateTime.Now.AddDays(-7)))
|
||||
.Sum(y => y.ViewCount) <= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumViewCountLastYearFromFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumViewCountLastYearFromFilter(long? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.ViewCounts
|
||||
.Where(y => y.Date >= DateOnly.FromDateTime(DateTime.Now.AddYears(-1)))
|
||||
.Sum(y => y.ViewCount) >= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
|
||||
public record MediumViewCountLastYearToFilter<T> : Filter<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
public MediumViewCountLastYearToFilter(long? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.ViewCounts
|
||||
.Where(y => y.Date >= DateOnly.FromDateTime(DateTime.Now.AddYears(-1)))
|
||||
.Sum(y => y.ViewCount) <= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Linq.Expressions;
|
||||
using WatchIt.Database.Model.Media;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium;
|
||||
|
||||
public static class MediumOrderKeys
|
||||
{
|
||||
public static Dictionary<string, Expression<Func<T, object?>>> Base<T>() where T : Database.Model.Media.Medium => new Dictionary<string, Expression<Func<T, object?>>>
|
||||
{
|
||||
{ "id", x => x.Id },
|
||||
{ "title", x => x.Title },
|
||||
{ "original_title", x => x.OriginalTitle },
|
||||
{ "description", x => x.Description },
|
||||
{ "release_date", x => x.ReleaseDate },
|
||||
{ "rating.average", x => x.Ratings.Any() ? x.Ratings.Average(y => y.Rating) : 0 },
|
||||
{ "rating.count", x => x.Ratings.Count() },
|
||||
{ "view_count.last_24_hours", x => x.ViewCounts.Where(y => y.Date.ToDateTime(new TimeOnly(23, 59)) >= DateTime.Now.AddDays(-1)).Sum(y => y.ViewCount) },
|
||||
{ "view_count.last_week", x => x.ViewCounts.Where(y => y.Date.ToDateTime(new TimeOnly(23, 59)) >= DateTime.Now.AddDays(-7)).Sum(y => y.ViewCount) },
|
||||
{ "view_count.last_month", x => x.ViewCounts.Where(y => y.Date.ToDateTime(new TimeOnly(23, 59)) >= DateTime.Now.AddMonths(-1)).Sum(y => y.ViewCount) },
|
||||
{ "view_count.last_year", x => x.ViewCounts.Where(y => y.Date.ToDateTime(new TimeOnly(23, 59)) >= DateTime.Now.AddYears(-1)).Sum(y => y.ViewCount) }
|
||||
};
|
||||
|
||||
public static readonly Dictionary<string, Expression<Func<Database.Model.Media.Medium, object?>>> Medium = new Dictionary<string, Expression<Func<Database.Model.Media.Medium, object?>>>
|
||||
{
|
||||
{ "type", x => x.Type },
|
||||
};
|
||||
|
||||
public static readonly Dictionary<string, Expression<Func<MediumMovie, object?>>> MediumMovie = new Dictionary<string, Expression<Func<MediumMovie, object?>>>
|
||||
{
|
||||
{ "budget", x => x.Budget },
|
||||
};
|
||||
|
||||
public static readonly Dictionary<string, Expression<Func<MediumSeries, object?>>> MediumSeries = new Dictionary<string, Expression<Func<MediumSeries, object?>>>
|
||||
{
|
||||
{ "has_ended", x => x.HasEnded },
|
||||
};
|
||||
|
||||
public static Dictionary<string, Expression<Func<T, object?>>> MediumUserRated<T>(long accountId) where T : Database.Model.Media.Medium => new Dictionary<string, Expression<Func<T, object?>>>
|
||||
{
|
||||
{ "rating_user.rating", x => x.Ratings.FirstOrDefault(x => x.AccountId == accountId) != null ? x.Ratings.FirstOrDefault(x => x.AccountId == accountId).Rating : null },
|
||||
{ "rating_user.date", x => x.Ratings.FirstOrDefault(x => x.AccountId == accountId) != null ? x.Ratings.FirstOrDefault(x => x.AccountId == accountId).Date : null },
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Refit;
|
||||
using WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Query;
|
||||
|
||||
public class BaseMediumFilterQuery<T> : IFilterQuery<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
[FromQuery(Name = "title")]
|
||||
public string? Title { get; set; }
|
||||
|
||||
[FromQuery(Name = "original_title")]
|
||||
[AliasAs("original_title")]
|
||||
public string? OriginalTitle { get; set; }
|
||||
|
||||
[FromQuery(Name = "description")]
|
||||
public string? Description { get; set; }
|
||||
|
||||
[FromQuery(Name = "release_date_from")]
|
||||
[AliasAs("release_date_from")]
|
||||
public DateOnly? ReleaseDateFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "release_date_to")]
|
||||
[AliasAs("release_date_to")]
|
||||
public DateOnly? ReleaseDateTo { get; set; }
|
||||
|
||||
[AliasAs("genre")]
|
||||
[FromQuery(Name = "genre")]
|
||||
public IEnumerable<short>? Genres { get; set; }
|
||||
|
||||
[FromQuery(Name = "rating_average_from")]
|
||||
[AliasAs("rating_average_from")]
|
||||
public decimal? RatingAverageFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "rating_average_to")]
|
||||
[AliasAs("rating_average_to")]
|
||||
public decimal? RatingAverageTo { get; set; }
|
||||
|
||||
[FromQuery(Name = "rating_count_from")]
|
||||
[AliasAs("rating_count_from")]
|
||||
public long? RatingCountFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "rating_count_to")]
|
||||
[AliasAs("rating_count_to")]
|
||||
public long? RatingCountTo { get; set; }
|
||||
|
||||
[FromQuery(Name = "view_count_last_24_hours_from")]
|
||||
[AliasAs("view_count_last_24_hours_from")]
|
||||
public long? ViewCountLast24HoursFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "view_count_last_24_hours_from")]
|
||||
[AliasAs("view_count_last_24_hours_from")]
|
||||
public long? ViewCountLast24HoursTo { get; set; }
|
||||
|
||||
[FromQuery(Name = "view_count_last_week_from")]
|
||||
[AliasAs("view_count_last_week_from")]
|
||||
public long? ViewCountLastWeekFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "view_count_last_week_to")]
|
||||
[AliasAs("view_count_last_week_to")]
|
||||
public long? ViewCountLastWeekTo { get; set; }
|
||||
|
||||
[FromQuery(Name = "view_count_last_month_from")]
|
||||
[AliasAs("view_count_last_month_from")]
|
||||
public long? ViewCountLastMonthFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "view_count_last_month_to")]
|
||||
[AliasAs("view_count_last_month_to")]
|
||||
public long? ViewCountLastMonthTo { get; set; }
|
||||
|
||||
[FromQuery(Name = "view_count_last_year_from")]
|
||||
[AliasAs("view_count_last_year_from")]
|
||||
public long? ViewCountLastYearFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "view_count_last_year_to")]
|
||||
[AliasAs("view_count_last_year_to")]
|
||||
public long? ViewCountLastYearTo { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public virtual IEnumerable<Filter<T>> GetFilters() =>
|
||||
[
|
||||
new MediumTitleFilter<T>(Title),
|
||||
new MediumOriginalTitleFilter<T>(OriginalTitle),
|
||||
new MediumDescriptionFilter<T>(Description),
|
||||
new MediumReleaseDateFromFilter<T>(ReleaseDateFrom),
|
||||
new MediumReleaseDateToFilter<T>(ReleaseDateTo),
|
||||
new MediumGenresFilter<T>(Genres),
|
||||
new MediumRatingAverageFromFilter<T>(RatingAverageFrom),
|
||||
new MediumRatingAverageToFilter<T>(RatingAverageTo),
|
||||
new MediumRatingCountFromFilter<T>(RatingCountFrom),
|
||||
new MediumRatingCountToFilter<T>(RatingCountTo),
|
||||
new MediumViewCountLast24HoursFromFilter<T>(ViewCountLast24HoursFrom),
|
||||
new MediumViewCountLast24HoursToFilter<T>(ViewCountLast24HoursTo),
|
||||
new MediumViewCountLastWeekFromFilter<T>(ViewCountLastWeekFrom),
|
||||
new MediumViewCountLastWeekToFilter<T>(ViewCountLastWeekTo),
|
||||
new MediumViewCountLastMonthFromFilter<T>(ViewCountLastMonthFrom),
|
||||
new MediumViewCountLastMonthToFilter<T>(ViewCountLastMonthTo),
|
||||
new MediumViewCountLastYearFromFilter<T>(ViewCountLastYearFrom),
|
||||
new MediumViewCountLastYearToFilter<T>(ViewCountLastYearTo),
|
||||
];
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using WatchIt.Database.Model.Media;
|
||||
using WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Query;
|
||||
|
||||
public class MediumFilterQuery : BaseMediumFilterQuery<Database.Model.Media.Medium>
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
[FromQuery(Name = "type")]
|
||||
public MediumType? Type { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public override IEnumerable<Filter<Database.Model.Media.Medium>> GetFilters() => base.GetFilters()
|
||||
.Append(new MediumTypeFilter(Type));
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Refit;
|
||||
using WatchIt.Database.Model.Media;
|
||||
using WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Query;
|
||||
|
||||
public class MediumMovieFilterQuery : BaseMediumFilterQuery<MediumMovie>
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
[FromQuery(Name = "budget_from")]
|
||||
[AliasAs("budget_from")]
|
||||
public decimal? BudgetFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "budget_to")]
|
||||
[AliasAs("budget_to")]
|
||||
public decimal? BudgetTo { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public override IEnumerable<Filter<MediumMovie>> GetFilters() => base.GetFilters()
|
||||
.Append(new MediumMovieBudgetFromFilter(BudgetFrom))
|
||||
.Append(new MediumMovieBudgetToFilter(BudgetTo));
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Refit;
|
||||
using WatchIt.Database.Model.Media;
|
||||
using WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Query;
|
||||
|
||||
public class MediumSeriesFilterQuery : BaseMediumFilterQuery<MediumSeries>
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
[FromQuery(Name = "has_ended")]
|
||||
[AliasAs("has_ended")]
|
||||
public bool? HasEnded { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public override IEnumerable<Filter<MediumSeries>> GetFilters() => base.GetFilters()
|
||||
.Append(new MediumSeriesHasEndedFilter(HasEnded));
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Refit;
|
||||
using WatchIt.DTO.Models.Controllers.Media.Medium.Filters;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Query;
|
||||
|
||||
public class MediumUserRatedFilterQuery<T> : IFilterQuery<T> where T : Database.Model.Media.Medium
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
[FromQuery(Name = "rating_user_rating_from")]
|
||||
[AliasAs("rating_user_rating_from")]
|
||||
public byte? RatingUserRatingFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "rating_user_rating_to")]
|
||||
[AliasAs("rating_user_rating_to")]
|
||||
public byte? RatingUserRatingTo { get; set; }
|
||||
|
||||
[FromQuery(Name = "rating_user_date_from")]
|
||||
[AliasAs("rating_user_date_from")]
|
||||
public DateOnly? RatingUserDateFrom { get; set; }
|
||||
|
||||
[FromQuery(Name = "rating_user_date_to")]
|
||||
[AliasAs("rating_user_date_to")]
|
||||
public DateOnly? RatingUserDateTo { get; set; }
|
||||
|
||||
|
||||
[FromRoute(Name = "id")]
|
||||
public long AccountId { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public IEnumerable<Filter<T>> GetFilters() =>
|
||||
[
|
||||
new MediumRatingUserRatingFromFilter<T>(RatingUserRatingFrom, AccountId),
|
||||
new MediumRatingUserRatingToFilter<T>(RatingUserRatingTo, AccountId),
|
||||
new MediumRatingUserDateFromFilter<T>(RatingUserDateFrom, AccountId),
|
||||
new MediumRatingUserDateToFilter<T>(RatingUserDateTo, AccountId)
|
||||
];
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Request;
|
||||
|
||||
public class MediumMovieRequest : MediumRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public decimal? Budget { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Request;
|
||||
|
||||
public abstract class MediumRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public string Title { get; set; } = null!;
|
||||
public string? OriginalTitle { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public DateOnly? ReleaseDate { get; set; }
|
||||
public short? Duration { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Request;
|
||||
|
||||
public class MediumSeriesRequest : MediumRequest
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public bool HasEnded { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using WatchIt.DTO.Models.Controllers.Genres.Genre;
|
||||
using WatchIt.DTO.Models.Generics.Image;
|
||||
using WatchIt.DTO.Models.Generics.Rating;
|
||||
using WatchIt.DTO.Models.Generics.ViewCount;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Response;
|
||||
|
||||
public abstract class BaseMediumResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public long Id { get; set; }
|
||||
public string Title { get; set; } = null!;
|
||||
public string? OriginalTitle { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public DateOnly? ReleaseDate { get; set; }
|
||||
public short? Duration { get; set; }
|
||||
public IEnumerable<GenreResponse> Genres { get; set; } = null!;
|
||||
public RatingOverallResponse Rating { get; set; } = null!;
|
||||
public ViewCountResponse ViewCount { get; set; } = null!;
|
||||
public ImageResponse? Picture { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using WatchIt.DTO.Models.Generics.Rating;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Response;
|
||||
|
||||
public interface IMediumUserRatedResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
RatingUserResponse? RatingUser { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Response;
|
||||
|
||||
public class MediumMovieResponse : BaseMediumResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public decimal? Budget { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using WatchIt.DTO.Models.Generics.Rating;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Response;
|
||||
|
||||
public class MediumMovieUserRatedResponse : MediumMovieResponse, IMediumUserRatedResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public RatingUserResponse? RatingUser { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Response;
|
||||
|
||||
public class MediumResponse : BaseMediumResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public MediumResponseType Type { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Response;
|
||||
|
||||
public enum MediumResponseType
|
||||
{
|
||||
Movie = 0,
|
||||
Series = 1,
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Response;
|
||||
|
||||
public class MediumSeriesResponse : BaseMediumResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public bool HasEnded { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using WatchIt.DTO.Models.Generics.Rating;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Response;
|
||||
|
||||
public class MediumSeriesUserRatedResponse : MediumSeriesResponse, IMediumUserRatedResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public RatingUserResponse? RatingUser { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using WatchIt.DTO.Models.Generics.Rating;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.Media.Medium.Response;
|
||||
|
||||
public class MediumUserRatedResponse : MediumResponse, IMediumUserRatedResponse
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public RatingUserResponse? RatingUser { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
108
WatchIt.DTO/Models/Controllers/People/PeopleMappers.cs
Normal file
108
WatchIt.DTO/Models/Controllers/People/PeopleMappers.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using WatchIt.Database.Model.People;
|
||||
using WatchIt.DTO.Models.Controllers.Genders;
|
||||
using WatchIt.DTO.Models.Controllers.People.Person;
|
||||
using WatchIt.DTO.Models.Generics.Image;
|
||||
using WatchIt.DTO.Models.Generics.Rating;
|
||||
using WatchIt.DTO.Models.Generics.ViewCount;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.People;
|
||||
|
||||
public static class PeopleMappers
|
||||
{
|
||||
#region PUBLIC METHODS
|
||||
|
||||
#region Person
|
||||
|
||||
public static Database.Model.People.Person ToEntity(this PersonRequest request) => new Database.Model.People.Person
|
||||
{
|
||||
Name = request.Name,
|
||||
FullName = request.FullName,
|
||||
Description = request.Description,
|
||||
BirthDate = request.BirthDate,
|
||||
DeathDate = request.DeathDate,
|
||||
GenderId = request.GenderId,
|
||||
};
|
||||
|
||||
public static void UpdateWithRequest(this Database.Model.People.Person entity, PersonRequest request)
|
||||
{
|
||||
entity.Name = request.Name;
|
||||
entity.FullName = request.FullName;
|
||||
entity.Description = request.Description;
|
||||
entity.BirthDate = request.BirthDate;
|
||||
entity.DeathDate = request.DeathDate;
|
||||
entity.GenderId = request.GenderId;
|
||||
}
|
||||
|
||||
public static PersonResponse ToResponse(this Database.Model.People.Person entity)
|
||||
{
|
||||
PersonResponse response = new PersonResponse();
|
||||
response.SetPersonResponseProperties(entity);
|
||||
return response;
|
||||
}
|
||||
|
||||
public static PersonUserRatedResponse ToResponse(this Database.Model.People.Person entity, long accountId)
|
||||
{
|
||||
PersonUserRatedResponse response = new PersonUserRatedResponse();
|
||||
response.SetPersonResponseProperties(entity);
|
||||
response.RatingUser = entity.Roles
|
||||
.SelectMany(x => x.Ratings
|
||||
.Where(y => y.AccountId == accountId))
|
||||
.ToUserOverallResponse();
|
||||
return response;
|
||||
}
|
||||
|
||||
public static PersonRequest ToRequest(this PersonResponse response) => new PersonRequest
|
||||
{
|
||||
Name = response.Name,
|
||||
FullName = response.FullName,
|
||||
Description = response.Description,
|
||||
BirthDate = response.BirthDate,
|
||||
DeathDate = response.DeathDate,
|
||||
GenderId = response.Gender?.Id,
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region PersonPicture
|
||||
|
||||
public static Database.Model.People.PersonPicture ToEntity(this ImageRequest request, long personId) => new Database.Model.People.PersonPicture
|
||||
{
|
||||
PersonId = personId,
|
||||
Image = request.Image,
|
||||
MimeType = request.MimeType,
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region MediumViewCount
|
||||
|
||||
public static PersonViewCount CreatePersonViewCountEntity(long personId) => new PersonViewCount
|
||||
{
|
||||
PersonId = personId,
|
||||
ViewCount = 1,
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
private static void SetPersonResponseProperties(this PersonResponse response, Database.Model.People.Person entity)
|
||||
{
|
||||
response.Id = entity.Id;
|
||||
response.Name = entity.Name;
|
||||
response.FullName = entity.FullName;
|
||||
response.Description = entity.Description;
|
||||
response.BirthDate = entity.BirthDate;
|
||||
response.DeathDate = entity.DeathDate;
|
||||
response.Gender = entity.Gender?.ToResponse();
|
||||
response.Rating = entity.Roles.SelectMany(x => x.Ratings).ToOverallResponse();
|
||||
response.ViewCount = entity.ViewCounts.ToResponse();
|
||||
response.Picture = entity.Picture?.ToResponse();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.People.Person.Filters;
|
||||
|
||||
public record PersonBirthDateFromFilter : Filter<Database.Model.People.Person>
|
||||
{
|
||||
public PersonBirthDateFromFilter(DateOnly? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.BirthDate >= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.People.Person.Filters;
|
||||
|
||||
public record PersonBirthDateToFilter : Filter<Database.Model.People.Person>
|
||||
{
|
||||
public PersonBirthDateToFilter(DateOnly? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.BirthDate <= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.People.Person.Filters;
|
||||
|
||||
public record PersonDeathDateFromFilter : Filter<Database.Model.People.Person>
|
||||
{
|
||||
public PersonDeathDateFromFilter(DateOnly? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.DeathDate >= query
|
||||
)) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.DTO.Models.Controllers.People.Person.Filters;
|
||||
|
||||
public record PersonDeathDateToFilter : Filter<Database.Model.People.Person>
|
||||
{
|
||||
public PersonDeathDateToFilter(DateOnly? query) : base(x =>
|
||||
(
|
||||
query == null
|
||||
||
|
||||
x.DeathDate <= query
|
||||
)) { }
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user