diff --git a/WatchIt.Common/WatchIt.Common.Model/Genres/GenreQueryParameters.cs b/WatchIt.Common/WatchIt.Common.Model/Genres/GenreQueryParameters.cs index 9b70ddb..f5efe40 100644 --- a/WatchIt.Common/WatchIt.Common.Model/Genres/GenreQueryParameters.cs +++ b/WatchIt.Common/WatchIt.Common.Model/Genres/GenreQueryParameters.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using WatchIt.Common.Query; namespace WatchIt.Common.Model.Genres; diff --git a/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhoto.cs b/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhoto.cs new file mode 100644 index 0000000..aa76ffd --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhoto.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; + +namespace WatchIt.Common.Model.Media; + +public class MediaPhoto +{ + [JsonPropertyName("media_id")] + public required long MediaId { get; set; } + + [JsonPropertyName("image")] + public required byte[] Image { get; set; } + + [JsonPropertyName("mime_type")] + public required string MimeType { get; set; } + + [JsonPropertyName("background")] + public MediaPhotoBackground? Background { get; set; } +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoBackground.cs b/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoBackground.cs new file mode 100644 index 0000000..bb46b23 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoBackground.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace WatchIt.Common.Model.Media; + +public class MediaPhotoBackground +{ + [JsonPropertyName("is_universal_background")] + public required bool IsUniversalBackground { get; set; } + + [JsonPropertyName("first_gradient_color")] + public required byte[] FirstGradientColor { get; set; } + + [JsonPropertyName("second_gradient_color")] + public required byte[] SecondGradientColor { get; set; } +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoQueryParameters.cs b/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoQueryParameters.cs new file mode 100644 index 0000000..83777b0 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoQueryParameters.cs @@ -0,0 +1,36 @@ +using System.Text; +using Microsoft.AspNetCore.Mvc; +using WatchIt.Common.Query; + +namespace WatchIt.Common.Model.Media; + +public class MediaPhotoQueryParameters : QueryParameters +{ + #region PROPERTIES + + [FromQuery(Name = "mime_type")] + public string? MimeType { get; set; } + + [FromQuery(Name = "is_background")] + public bool? IsBackground { get; set; } + + [FromQuery(Name = "is_universal_background")] + public bool? IsUniversalBackground { get; set; } + + #endregion + + + + #region PUBLIC METHODS + + public override bool IsMeetingConditions(MediaPhotoResponse item) => + ( + TestString(item.MimeType, MimeType) + && + TestBoolean(item.Background is not null, IsBackground) + && + TestBoolean(item.Background!.IsUniversalBackground, IsUniversalBackground) + ); + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoRequest.cs b/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoRequest.cs new file mode 100644 index 0000000..b365b12 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoRequest.cs @@ -0,0 +1,38 @@ +using WatchIt.Database.Model.Media; + +namespace WatchIt.Common.Model.Media; + +public class MediaPhotoRequest : MediaPhoto +{ + public MediaPhotoImage CreateMediaPhotoImage() => new MediaPhotoImage + { + MediaId = MediaId, + Image = Image, + MimeType = MimeType + }; + + public MediaPhotoImageBackground? CreateMediaPhotoImageBackground(Guid mediaPhotoImageId) => Background is null ? null : new MediaPhotoImageBackground + { + Id = mediaPhotoImageId, + IsUniversalBackground = Background.IsUniversalBackground, + FirstGradientColor = Background.FirstGradientColor, + SecondGradientColor = Background.SecondGradientColor + }; + + public void UpdateMediaPhotoImage(MediaPhotoImage item) + { + item.MediaId = MediaId; + item.Image = Image; + item.MimeType = MimeType; + } + + public void UpdateMediaPhotoImageBackground(MediaPhotoImageBackground item) + { + if (Background is not null) + { + item.IsUniversalBackground = Background.IsUniversalBackground; + item.FirstGradientColor = Background.FirstGradientColor; + item.SecondGradientColor = Background.SecondGradientColor; + } + } +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoResponse.cs b/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoResponse.cs new file mode 100644 index 0000000..e2e1ec5 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Media/MediaPhotoResponse.cs @@ -0,0 +1,47 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; +using WatchIt.Database.Model.Media; + +namespace WatchIt.Common.Model.Media; + +public class MediaPhotoResponse : MediaPhoto +{ + #region PROPERTIES + + [JsonPropertyName("id")] + public Guid Id { get; set; } + + [JsonPropertyName("upload_date")] + public DateTime UploadDate { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + [JsonConstructor] + public MediaPhotoResponse() {} + + [SetsRequiredMembers] + public MediaPhotoResponse(MediaPhotoImage mediaPhotoImage) + { + Id = mediaPhotoImage.Id; + MediaId = mediaPhotoImage.MediaId; + Image = mediaPhotoImage.Image; + MimeType = mediaPhotoImage.MimeType; + UploadDate = mediaPhotoImage.UploadDate; + + if (mediaPhotoImage.MediaPhotoImageBackground is not null) + { + Background = new MediaPhotoBackground + { + IsUniversalBackground = mediaPhotoImage.MediaPhotoImageBackground.IsUniversalBackground, + FirstGradientColor = mediaPhotoImage.MediaPhotoImageBackground.FirstGradientColor, + SecondGradientColor = mediaPhotoImage.MediaPhotoImageBackground.SecondGradientColor + }; + } + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Model/Movies/MovieQueryParameters.cs b/WatchIt.Common/WatchIt.Common.Model/Movies/MovieQueryParameters.cs index 11f01e3..bffef31 100644 --- a/WatchIt.Common/WatchIt.Common.Model/Movies/MovieQueryParameters.cs +++ b/WatchIt.Common/WatchIt.Common.Model/Movies/MovieQueryParameters.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using WatchIt.Common.Query; namespace WatchIt.Common.Model.Movies; diff --git a/WatchIt.Common/WatchIt.Common.Model/Movies/MovieRequest.cs b/WatchIt.Common/WatchIt.Common.Model/Movies/MovieRequest.cs index c357054..ab103fa 100644 --- a/WatchIt.Common/WatchIt.Common.Model/Movies/MovieRequest.cs +++ b/WatchIt.Common/WatchIt.Common.Model/Movies/MovieRequest.cs @@ -6,7 +6,7 @@ public class MovieRequest : Movie { #region PUBLIC METHODS - public Media CreateMedia() => new Media + public Database.Model.Media.Media CreateMedia() => new Database.Model.Media.Media { Title = Title, OriginalTitle = OriginalTitle, @@ -21,7 +21,7 @@ public class MovieRequest : Movie Budget = Budget, }; - public void UpdateMedia(Media media) + public void UpdateMedia(Database.Model.Media.Media media) { media.Title = Title; media.OriginalTitle = OriginalTitle; diff --git a/WatchIt.Common/WatchIt.Common.Model/WatchIt.Common.Model.csproj b/WatchIt.Common/WatchIt.Common.Model/WatchIt.Common.Model.csproj index dc1e5db..066e490 100644 --- a/WatchIt.Common/WatchIt.Common.Model/WatchIt.Common.Model.csproj +++ b/WatchIt.Common/WatchIt.Common.Model/WatchIt.Common.Model.csproj @@ -8,6 +8,7 @@ + diff --git a/WatchIt.Common/WatchIt.Common.Model/QueryParameters.cs b/WatchIt.Common/WatchIt.Common.Query/QueryParameters.cs similarity index 67% rename from WatchIt.Common/WatchIt.Common.Model/QueryParameters.cs rename to WatchIt.Common/WatchIt.Common.Query/QueryParameters.cs index b3d983b..685da26 100644 --- a/WatchIt.Common/WatchIt.Common.Model/QueryParameters.cs +++ b/WatchIt.Common/WatchIt.Common.Query/QueryParameters.cs @@ -1,11 +1,12 @@ using System.Reflection; +using System.Text; using System.Text.Json.Serialization; using System.Text.RegularExpressions; using Microsoft.AspNetCore.Mvc; -namespace WatchIt.Common.Model; +namespace WatchIt.Common.Query; -public abstract class QueryParameters where T : class +public abstract class QueryParameters { #region PROPERTIES @@ -22,9 +23,93 @@ public abstract class QueryParameters where T : class public int? After { get; set; } #endregion + + + + #region PUBLIC METHODS + + public override string ToString() + { + List queries = new List(); + PropertyInfo[] properties = this.GetType().GetProperties(); + foreach (PropertyInfo property in properties) + { + object? value = property.GetValue(this); + FromQueryAttribute? attribute = property.GetCustomAttributes(true).FirstOrDefault(); + if (value is not null && attribute is not null) + { + string query = $"{attribute.Name}={value}"; + queries.Add(query); + } + } + + return $"?{string.Join('&', queries)}"; + } + + #endregion + #region PRIVATE METHODS + + protected static bool TestBoolean(bool property, bool? query) => + ( + query is null + || + property == query + ); + + protected static bool TestString(string? property, string? regexQuery) => + ( + string.IsNullOrEmpty(regexQuery) + || + ( + !string.IsNullOrEmpty(property) + && + new Regex(regexQuery).IsMatch(property) + ) + ); + + protected static bool TestComparable(IComparable? property, IComparable? exact, IComparable? from, IComparable? to) => + ( + ( + exact is null + || + ( + property is not null + && + property.CompareTo(exact) == 0 + ) + ) + && + ( + from is null + || + ( + property is not null + && + property.CompareTo(from) > 0 + ) + ) + && + ( + to is null + || + ( + property is not null + && + property.CompareTo(to) < 0 + ) + ) + ); + + #endregion +} + + + +public abstract class QueryParameters : QueryParameters where T : class +{ #region PUBLIC METHODS public abstract bool IsMeetingConditions(T item); @@ -65,54 +150,4 @@ public abstract class QueryParameters where T : class } #endregion - - - - #region PRIVATE METHODS - - protected bool TestString(string? property, string? regexQuery) => - ( - string.IsNullOrEmpty(regexQuery) - || - ( - !string.IsNullOrEmpty(property) - && - new Regex(regexQuery).IsMatch(property) - ) - ); - - protected bool TestComparable(IComparable? property, IComparable? exact, IComparable? from, IComparable? to) => - ( - ( - exact is null - || - ( - property is not null - && - property.CompareTo(exact) == 0 - ) - ) - && - ( - from is null - || - ( - property is not null - && - property.CompareTo(from) > 0 - ) - ) - && - ( - to is null - || - ( - property is not null - && - property.CompareTo(to) < 0 - ) - ) - ); - - #endregion } \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Query/WatchIt.Common.Query.csproj b/WatchIt.Common/WatchIt.Common.Query/WatchIt.Common.Query.csproj new file mode 100644 index 0000000..dd9b769 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Query/WatchIt.Common.Query.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpClientService.cs b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpClientService.cs new file mode 100644 index 0000000..3f53246 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpClientService.cs @@ -0,0 +1,43 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace WatchIt.Common.Services.HttpClient; + +public class HttpClientService(System.Net.Http.HttpClient httpClient) : IHttpClientService +{ + #region PUBLIC METHODS + + public async Task SendRequestAsync(HttpRequest request) + { + HttpMethod method = request.MethodType switch + { + HttpMethodType.Get => HttpMethod.Get, + HttpMethodType.Post => HttpMethod.Post, + HttpMethodType.Put => HttpMethod.Put, + HttpMethodType.Patch => HttpMethod.Patch, + HttpMethodType.Delete => HttpMethod.Delete, + _ => throw new ArgumentOutOfRangeException() + }; + + HttpRequestMessage httpRequest = new HttpRequestMessage(method, request.FullUrl); + + if (request.Body is not null) + { + string json = JsonSerializer.Serialize(request.Body); + HttpContent content = new StringContent(json); + content.Headers.ContentType!.MediaType = "application/json"; + httpRequest.Content = content; + } + + foreach (KeyValuePair header in request.Headers) + { + httpRequest.Headers.Add(header.Key, header.Value); + } + + HttpResponseMessage response = await httpClient.SendAsync(httpRequest); + + return new HttpResponse(response); + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpMethodType.cs b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpMethodType.cs new file mode 100644 index 0000000..79611b6 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpMethodType.cs @@ -0,0 +1,10 @@ +namespace WatchIt.Common.Services.HttpClient; + +public enum HttpMethodType +{ + Get, + Post, + Put, + Patch, + Delete +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpRequest.cs b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpRequest.cs new file mode 100644 index 0000000..c0c0149 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpRequest.cs @@ -0,0 +1,32 @@ +using System.Diagnostics.CodeAnalysis; +using WatchIt.Common.Query; + +namespace WatchIt.Common.Services.HttpClient; + +public class HttpRequest +{ + #region PROPERTIES + + public required HttpMethodType MethodType { get; set; } + public required string Url { get; set; } + public QueryParameters? Query { get; set; } + public object? Body { get; set; } + public Dictionary Headers { get; } = new Dictionary(); + + public string FullUrl => $"{Url}{(Query is not null ? Query.ToString() : string.Empty)}"; + + #endregion + + + + #region CONSTRUCTORS + + [SetsRequiredMembers] + public HttpRequest(HttpMethodType methodType, string url) + { + MethodType = methodType; + Url = url; + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpResponse.cs b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpResponse.cs new file mode 100644 index 0000000..0edbd6b --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/HttpResponse.cs @@ -0,0 +1,107 @@ +using System.Text.Json; +using Microsoft.AspNetCore.Mvc; + +namespace WatchIt.Common.Services.HttpClient; + +public class HttpResponse +{ + #region FIELDS + + private HttpResponseMessage _message; + + private Action? _2XXAction; + private Action? _400Action; + private Action? _401Action; + private Action? _403Action; + private Action? _404Action; + + #endregion + + + + #region CONSTRUCTORS + + internal HttpResponse(HttpResponseMessage message) + { + _message = message; + } + + #endregion + + + + #region PUBLIC METHODS + + public HttpResponse RegisterActionFor2XXSuccess(Action action) + { + _2XXAction = action; + return this; + } + + public HttpResponse RegisterActionFor2XXSuccess(Action action) + { + _2XXAction = () => Invoke(action); + return this; + } + + public HttpResponse RegisterActionFor400BadRequest(Action> action) + { + _400Action = () => Invoke(action); + return this; + } + + public HttpResponse RegisterActionFor401Unauthorized(Action action) + { + _401Action = action; + return this; + } + + public HttpResponse RegisterActionFor403Forbidden(Action action) + { + _403Action = action; + return this; + } + + public HttpResponse RegisterActionFor404NotFound(Action action) + { + _404Action = action; + return this; + } + + public void ExecuteAction() + { + switch ((int)_message.StatusCode) + { + case >= 200 and <= 299: _2XXAction?.Invoke(); break; + case 400: _400Action?.Invoke(); break; + case 401: _401Action?.Invoke(); break; + case 403: _403Action?.Invoke(); break; + case 404: _404Action?.Invoke(); break; + } + } + + #endregion + + + + #region PRIVATE METHODS + + private async void Invoke(Action action) + { + Stream streamData = await _message.Content.ReadAsStreamAsync(); + T? data = await JsonSerializer.DeserializeAsync(streamData); + action.Invoke(data!); + } + + private async void Invoke(Action> action) + { + Stream streamData = await _message.Content.ReadAsStreamAsync(); + ValidationProblemDetails? data = await JsonSerializer.DeserializeAsync(streamData, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }); + action.Invoke(data!.Errors); + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/IHttpClientService.cs b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/IHttpClientService.cs new file mode 100644 index 0000000..484c01e --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/IHttpClientService.cs @@ -0,0 +1,6 @@ +namespace WatchIt.Common.Services.HttpClient; + +public interface IHttpClientService +{ + Task SendRequestAsync(HttpRequest request); +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/WatchIt.Common.Services.HttpClient.csproj b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/WatchIt.Common.Services.HttpClient.csproj new file mode 100644 index 0000000..026c6c4 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Services/WatchIt.Common.Services.HttpClient/WatchIt.Common.Services.HttpClient.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Media/MediaPhotoImageBackgroundConfiguration.cs b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Media/MediaPhotoImageBackgroundConfiguration.cs new file mode 100644 index 0000000..eab319d --- /dev/null +++ b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Media/MediaPhotoImageBackgroundConfiguration.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using WatchIt.Database.Model.Media; + +namespace WatchIt.Database.Model.Configuration.Media; + +public class MediaPhotoImageBackgroundConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(x => x.Id); + builder.HasIndex(x => x.Id) + .IsUnique(); + builder.Property(x => x.Id) + .IsRequired(); + + builder.Property(x => x.IsUniversalBackground) + .IsRequired() + .HasDefaultValue(false); + + builder.Property(x => x.FirstGradientColor) + .IsRequired() + .HasMaxLength(3); + + builder.Property(x => x.SecondGradientColor) + .IsRequired() + .HasMaxLength(3); + } +} \ No newline at end of file diff --git a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Media/MediaPhotoImageConfiguration.cs b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Media/MediaPhotoImageConfiguration.cs index c2476a1..b312d9c 100644 --- a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Media/MediaPhotoImageConfiguration.cs +++ b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Media/MediaPhotoImageConfiguration.cs @@ -33,12 +33,8 @@ public class MediaPhotoImageConfiguration : IEntityTypeConfiguration x.IsMediaBackground) - .IsRequired() - .HasDefaultValue(false); - - builder.Property(x => x.IsUniversalBackground) - .IsRequired() - .HasDefaultValue(false); + builder.HasOne(x => x.MediaPhotoImageBackground) + .WithOne(x => x.MediaPhotoImage) + .HasForeignKey(); } } \ No newline at end of file diff --git a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/WatchIt.Database.Model.Configuration.csproj b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/WatchIt.Database.Model.Configuration.csproj index 2c0e44b..96833d9 100644 --- a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/WatchIt.Database.Model.Configuration.csproj +++ b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/WatchIt.Database.Model.Configuration.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Media/MediaPhotoImage.cs b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Media/MediaPhotoImage.cs index 7c529b1..a94f8d7 100644 --- a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Media/MediaPhotoImage.cs +++ b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Media/MediaPhotoImage.cs @@ -9,8 +9,6 @@ public class MediaPhotoImage public required byte[] Image { get; set; } public required string MimeType { get; set; } public DateTime UploadDate { get; set; } - public bool IsMediaBackground { get; set; } - public bool IsUniversalBackground { get; set; } #endregion @@ -19,6 +17,7 @@ public class MediaPhotoImage #region NAVIGATION public virtual Media Media { get; set; } = null!; + public virtual MediaPhotoImageBackground? MediaPhotoImageBackground { get; set; } #endregion } \ No newline at end of file diff --git a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Media/MediaPhotoImageBackground.cs b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Media/MediaPhotoImageBackground.cs new file mode 100644 index 0000000..8d7cd83 --- /dev/null +++ b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Media/MediaPhotoImageBackground.cs @@ -0,0 +1,21 @@ +namespace WatchIt.Database.Model.Media; + +public class MediaPhotoImageBackground +{ + #region PROPERTIES + + public required Guid Id { get; set; } + public required bool IsUniversalBackground { get; set; } + public required byte[] FirstGradientColor { get; set; } + public required byte[] SecondGradientColor { get; set; } + + #endregion + + + + #region NAVIGATION + + public virtual MediaPhotoImage MediaPhotoImage { get; set; } = null!; + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Database/WatchIt.Database/DatabaseContext.cs b/WatchIt.Database/WatchIt.Database/DatabaseContext.cs index 9c3f546..977953d 100644 --- a/WatchIt.Database/WatchIt.Database/DatabaseContext.cs +++ b/WatchIt.Database/WatchIt.Database/DatabaseContext.cs @@ -51,6 +51,7 @@ public class DatabaseContext : DbContext public virtual DbSet MediaSeriesEpisodes { get; set; } public virtual DbSet MediaPosterImages { get; set; } public virtual DbSet MediaPhotoImages { get; set; } + public virtual DbSet MediaPhotoImageBackgrounds { get; set; } public virtual DbSet MediaGenres { get; set; } public virtual DbSet MediaProductionCountries { get; set; } diff --git a/WatchIt.Database/WatchIt.Database/Migrations/20240603125708_Initial.Designer.cs b/WatchIt.Database/WatchIt.Database/Migrations/20240603125708_Initial.Designer.cs new file mode 100644 index 0000000..644ec18 --- /dev/null +++ b/WatchIt.Database/WatchIt.Database/Migrations/20240603125708_Initial.Designer.cs @@ -0,0 +1,1397 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using WatchIt.Database; + +#nullable disable + +namespace WatchIt.Database.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20240603125708_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.5") + .HasAnnotation("Proxies:ChangeTracking", false) + .HasAnnotation("Proxies:CheckEquality", false) + .HasAnnotation("Proxies:LazyLoading", true) + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("WatchIt.Database.Model.Account.Account", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BackgroundPictureId") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("GenderId") + .HasColumnType("smallint"); + + b.Property("IsAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("LastActive") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("LeftSalt") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("bytea"); + + b.Property("ProfilePictureId") + .HasColumnType("uuid"); + + b.Property("RightSalt") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("BackgroundPictureId"); + + b.HasIndex("GenderId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("ProfilePictureId") + .IsUnique(); + + b.ToTable("Accounts"); + + b.HasData( + new + { + Id = 1L, + CreationDate = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + Email = "root@watch.it", + IsAdmin = true, + LastActive = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + LeftSalt = "Y&%]J>6Nc3&5~UUXnNxq", + Password = new byte[] { 68, 170, 8, 113, 134, 47, 98, 43, 96, 183, 126, 130, 204, 45, 4, 113, 81, 200, 244, 26, 54, 88, 161, 246, 84, 93, 159, 219, 12, 143, 128, 160, 198, 194, 47, 133, 216, 242, 158, 184, 43, 38, 134, 132, 175, 179, 42, 40, 0, 143, 111, 252, 156, 215, 17, 185, 12, 109, 119, 214, 211, 167, 32, 121 }, + RightSalt = "MV1jo~o3Oa^;NWb\\Q)t_", + Username = "root" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.AccountProfilePicture", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Image") + .IsRequired() + .HasMaxLength(-1) + .HasColumnType("bytea"); + + b.Property("MimeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UploadDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("AccountProfilePictures"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.AccountRefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("IsExtendable") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("AccountRefreshTokens"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Common.Country", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IsHistorical") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("Countries"); + + b.HasData( + new + { + Id = (short)1, + IsHistorical = false, + Name = "Afghanistan" + }, + new + { + Id = (short)2, + IsHistorical = false, + Name = "Albania" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Common.Gender", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("Genders"); + + b.HasData( + new + { + Id = (short)1, + Name = "Male" + }, + new + { + Id = (short)2, + Name = "Female" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Common.Genre", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("Genres"); + + b.HasData( + new + { + Id = (short)1, + Name = "Comedy" + }, + new + { + Id = (short)2, + Name = "Thriller" + }, + new + { + Id = (short)3, + Name = "Horror" + }, + new + { + Id = (short)4, + Name = "Action" + }, + new + { + Id = (short)5, + Name = "Drama" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.Media", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Length") + .HasColumnType("smallint"); + + b.Property("MediaPosterImageId") + .HasColumnType("uuid"); + + b.Property("OriginalTitle") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("ReleaseDate") + .HasColumnType("date"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaPosterImageId") + .IsUnique(); + + b.ToTable("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaGenre", b => + { + b.Property("GenreId") + .HasColumnType("smallint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.HasKey("GenreId", "MediaId"); + + b.HasIndex("MediaId"); + + b.ToTable("MediaGenres"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaMovie", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("Budget") + .HasColumnType("money"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("MediaMovies"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImage", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Image") + .IsRequired() + .HasMaxLength(-1) + .HasColumnType("bytea"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("MediaPhotoImageBackgroundId") + .HasColumnType("uuid"); + + b.Property("MimeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UploadDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaId"); + + b.HasIndex("MediaPhotoImageBackgroundId"); + + b.ToTable("MediaPhotoImages"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImageBackground", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("FirstGradientColor") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("bytea"); + + b.Property("IsUniversalBackground") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("SecondGradientColor") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("bytea"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("MediaPhotoImageBackgrounds"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPosterImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Image") + .IsRequired() + .HasMaxLength(-1) + .HasColumnType("bytea"); + + b.Property("MimeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UploadDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("MediaPosterImages"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaProductionCountry", b => + { + b.Property("CountryId") + .HasColumnType("smallint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.HasKey("CountryId", "MediaId"); + + b.HasIndex("MediaId"); + + b.ToTable("MediaProductionCountries"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeries", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("HasEnded") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("MediaSeries"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IsSpecial") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("MediaSeriesSeasonId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaSeriesSeasonId"); + + b.ToTable("MediaSeriesEpisodes"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesSeason", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MediaSeriesId") + .HasColumnType("bigint"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaSeriesId"); + + b.ToTable("MediaSeriesSeasons"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.Person", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BirthDate") + .HasColumnType("date"); + + b.Property("DeathDate") + .HasColumnType("date"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("FullName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("GenderId") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PersonPhotoId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GenderId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("PersonPhotoId") + .IsUnique(); + + b.ToTable("Persons"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonActorRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("PersonActorRoleTypeId") + .HasColumnType("smallint"); + + b.Property("PersonId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaId"); + + b.HasIndex("PersonActorRoleTypeId"); + + b.HasIndex("PersonId"); + + b.ToTable("PersonActorRoles"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonActorRoleType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("PersonActorRoleTypes"); + + b.HasData( + new + { + Id = (short)1, + Name = "Actor" + }, + new + { + Id = (short)2, + Name = "Supporting actor" + }, + new + { + Id = (short)3, + Name = "Voice actor" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonCreatorRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("PersonCreatorRoleTypeId") + .HasColumnType("smallint"); + + b.Property("PersonId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaId"); + + b.HasIndex("PersonCreatorRoleTypeId"); + + b.HasIndex("PersonId"); + + b.ToTable("PersonCreatorRoles"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonCreatorRoleType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("PersonCreatorRoleTypes"); + + b.HasData( + new + { + Id = (short)1, + Name = "Director" + }, + new + { + Id = (short)2, + Name = "Producer" + }, + new + { + Id = (short)3, + Name = "Screenwriter" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonPhotoImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Image") + .IsRequired() + .HasMaxLength(-1) + .HasColumnType("bytea"); + + b.Property("MimeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UploadDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("PersonPhotoImages"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMedia", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("Rating") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaId"); + + b.ToTable("RatingsMedia"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMediaSeriesEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("MediaSeriesEpisodeId") + .HasColumnType("uuid"); + + b.Property("Rating") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaSeriesEpisodeId"); + + b.ToTable("RatingsMediaSeriesEpisode"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMediaSeriesSeason", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("MediaSeriesSeasonId") + .HasColumnType("uuid"); + + b.Property("Rating") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaSeriesSeasonId"); + + b.ToTable("RatingsMediaSeriesSeason"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingPersonActorRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("PersonActorRoleId") + .HasColumnType("uuid"); + + b.Property("Rating") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("PersonActorRoleId"); + + b.ToTable("RatingsPersonActorRole", (string)null); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingPersonCreatorRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("PersonCreatorRoleId") + .HasColumnType("uuid"); + + b.Property("Rating") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("PersonCreatorRoleId"); + + b.ToTable("RatingsPersonCreatorRole", (string)null); + }); + + modelBuilder.Entity("WatchIt.Database.Model.ViewCount.ViewCountMedia", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Date") + .ValueGeneratedOnAdd() + .HasColumnType("date") + .HasDefaultValueSql("now()"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("ViewCount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaId"); + + b.ToTable("ViewCountsMedia", (string)null); + }); + + modelBuilder.Entity("WatchIt.Database.Model.ViewCount.ViewCountPerson", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Date") + .ValueGeneratedOnAdd() + .HasColumnType("date") + .HasDefaultValueSql("now()"); + + b.Property("PersonId") + .HasColumnType("bigint"); + + b.Property("ViewCount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("PersonId"); + + b.ToTable("ViewCountsPerson", (string)null); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.Account", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaPhotoImage", "BackgroundPicture") + .WithMany() + .HasForeignKey("BackgroundPictureId"); + + b.HasOne("WatchIt.Database.Model.Common.Gender", "Gender") + .WithMany() + .HasForeignKey("GenderId"); + + b.HasOne("WatchIt.Database.Model.Account.AccountProfilePicture", "ProfilePicture") + .WithOne("Account") + .HasForeignKey("WatchIt.Database.Model.Account.Account", "ProfilePictureId"); + + b.Navigation("BackgroundPicture"); + + b.Navigation("Gender"); + + b.Navigation("ProfilePicture"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.AccountRefreshToken", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("AccountRefreshTokens") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.Media", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaPosterImage", "MediaPosterImage") + .WithOne("Media") + .HasForeignKey("WatchIt.Database.Model.Media.Media", "MediaPosterImageId"); + + b.Navigation("MediaPosterImage"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaGenre", b => + { + b.HasOne("WatchIt.Database.Model.Common.Genre", "Genre") + .WithMany("MediaGenres") + .HasForeignKey("GenreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("MediaGenres") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Genre"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaMovie", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithOne() + .HasForeignKey("WatchIt.Database.Model.Media.MediaMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImage", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaPhotoImageBackground", null) + .WithOne("MediaPhotoImage") + .HasForeignKey("WatchIt.Database.Model.Media.MediaPhotoImage", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("MediaPhotoImages") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.MediaPhotoImageBackground", "MediaPhotoImageBackground") + .WithMany() + .HasForeignKey("MediaPhotoImageBackgroundId"); + + b.Navigation("Media"); + + b.Navigation("MediaPhotoImageBackground"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaProductionCountry", b => + { + b.HasOne("WatchIt.Database.Model.Common.Country", "Country") + .WithMany("MediaProductionCountries") + .HasForeignKey("CountryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("MediaProductionCountries") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Country"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeries", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithOne() + .HasForeignKey("WatchIt.Database.Model.Media.MediaSeries", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesEpisode", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaSeriesSeason", "MediaSeriesSeason") + .WithMany("MediaSeriesEpisodes") + .HasForeignKey("MediaSeriesSeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaSeriesSeason"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesSeason", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaSeries", "MediaSeries") + .WithMany("MediaSeriesSeasons") + .HasForeignKey("MediaSeriesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaSeries"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.Person", b => + { + b.HasOne("WatchIt.Database.Model.Common.Gender", "Gender") + .WithMany() + .HasForeignKey("GenderId"); + + b.HasOne("WatchIt.Database.Model.Person.PersonPhotoImage", "PersonPhoto") + .WithOne("Person") + .HasForeignKey("WatchIt.Database.Model.Person.Person", "PersonPhotoId"); + + b.Navigation("Gender"); + + b.Navigation("PersonPhoto"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonActorRole", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("PersonActorRoles") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.PersonActorRoleType", "PersonActorRoleType") + .WithMany() + .HasForeignKey("PersonActorRoleTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.Person", "Person") + .WithMany("PersonActorRoles") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("Person"); + + b.Navigation("PersonActorRoleType"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonCreatorRole", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("PersonCreatorRoles") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.PersonCreatorRoleType", "PersonCreatorRoleType") + .WithMany() + .HasForeignKey("PersonCreatorRoleTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.Person", "Person") + .WithMany("PersonCreatorRoles") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("Person"); + + b.Navigation("PersonCreatorRoleType"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMedia", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("RatingMedia") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("RatingMedia") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMediaSeriesEpisode", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("RatingMediaSeriesEpisode") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.MediaSeriesEpisode", "MediaSeriesEpisode") + .WithMany("RatingMediaSeriesEpisode") + .HasForeignKey("MediaSeriesEpisodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("MediaSeriesEpisode"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMediaSeriesSeason", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("RatingMediaSeriesSeason") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.MediaSeriesSeason", "MediaSeriesSeason") + .WithMany("RatingMediaSeriesSeason") + .HasForeignKey("MediaSeriesSeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("MediaSeriesSeason"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingPersonActorRole", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("RatingPersonActorRole") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.PersonActorRole", "PersonActorRole") + .WithMany("RatingPersonActorRole") + .HasForeignKey("PersonActorRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("PersonActorRole"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingPersonCreatorRole", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("RatingPersonCreatorRole") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.PersonCreatorRole", "PersonCreatorRole") + .WithMany("RatingPersonCreatorRole") + .HasForeignKey("PersonCreatorRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("PersonCreatorRole"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.ViewCount.ViewCountMedia", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("ViewCountsMedia") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.ViewCount.ViewCountPerson", b => + { + b.HasOne("WatchIt.Database.Model.Person.Person", "Person") + .WithMany("ViewCountsPerson") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.Account", b => + { + b.Navigation("AccountRefreshTokens"); + + b.Navigation("RatingMedia"); + + b.Navigation("RatingMediaSeriesEpisode"); + + b.Navigation("RatingMediaSeriesSeason"); + + b.Navigation("RatingPersonActorRole"); + + b.Navigation("RatingPersonCreatorRole"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.AccountProfilePicture", b => + { + b.Navigation("Account") + .IsRequired(); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Common.Country", b => + { + b.Navigation("MediaProductionCountries"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Common.Genre", b => + { + b.Navigation("MediaGenres"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.Media", b => + { + b.Navigation("MediaGenres"); + + b.Navigation("MediaPhotoImages"); + + b.Navigation("MediaProductionCountries"); + + b.Navigation("PersonActorRoles"); + + b.Navigation("PersonCreatorRoles"); + + b.Navigation("RatingMedia"); + + b.Navigation("ViewCountsMedia"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImageBackground", b => + { + b.Navigation("MediaPhotoImage") + .IsRequired(); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPosterImage", b => + { + b.Navigation("Media") + .IsRequired(); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeries", b => + { + b.Navigation("MediaSeriesSeasons"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesEpisode", b => + { + b.Navigation("RatingMediaSeriesEpisode"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesSeason", b => + { + b.Navigation("MediaSeriesEpisodes"); + + b.Navigation("RatingMediaSeriesSeason"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.Person", b => + { + b.Navigation("PersonActorRoles"); + + b.Navigation("PersonCreatorRoles"); + + b.Navigation("ViewCountsPerson"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonActorRole", b => + { + b.Navigation("RatingPersonActorRole"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonCreatorRole", b => + { + b.Navigation("RatingPersonCreatorRole"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonPhotoImage", b => + { + b.Navigation("Person") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/WatchIt.Database/WatchIt.Database/Migrations/20240418190404_0001_Initial.cs b/WatchIt.Database/WatchIt.Database/Migrations/20240603125708_Initial.cs similarity index 93% rename from WatchIt.Database/WatchIt.Database/Migrations/20240418190404_0001_Initial.cs rename to WatchIt.Database/WatchIt.Database/Migrations/20240603125708_Initial.cs index 4663b36..cf3eeb5 100644 --- a/WatchIt.Database/WatchIt.Database/Migrations/20240418190404_0001_Initial.cs +++ b/WatchIt.Database/WatchIt.Database/Migrations/20240603125708_Initial.cs @@ -9,7 +9,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace WatchIt.Database.Migrations { /// - public partial class _0001_Initial : Migration + public partial class Initial : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -62,13 +62,27 @@ namespace WatchIt.Database.Migrations Id = table.Column(type: "smallint", nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), Name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - Description = table.Column(type: "text", nullable: true) + Description = table.Column(type: "character varying(1000)", maxLength: 1000, nullable: true) }, constraints: table => { table.PrimaryKey("PK_Genres", x => x.Id); }); + migrationBuilder.CreateTable( + name: "MediaPhotoImageBackgrounds", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + IsUniversalBackground = table.Column(type: "boolean", nullable: false, defaultValue: false), + FirstGradientColor = table.Column(type: "bytea", maxLength: 3, nullable: false), + SecondGradientColor = table.Column(type: "bytea", maxLength: 3, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_MediaPhotoImageBackgrounds", x => x.Id); + }); + migrationBuilder.CreateTable( name: "MediaPosterImages", columns: table => new @@ -226,12 +240,22 @@ namespace WatchIt.Database.Migrations Image = table.Column(type: "bytea", maxLength: -1, nullable: false), MimeType = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), UploadDate = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"), - IsMediaBackground = table.Column(type: "boolean", nullable: false, defaultValue: false), - IsUniversalBackground = table.Column(type: "boolean", nullable: false, defaultValue: false) + MediaPhotoImageBackgroundId = table.Column(type: "uuid", nullable: true) }, constraints: table => { table.PrimaryKey("PK_MediaPhotoImages", x => x.Id); + table.ForeignKey( + name: "FK_MediaPhotoImages_MediaPhotoImageBackgrounds_Id", + column: x => x.Id, + principalTable: "MediaPhotoImageBackgrounds", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_MediaPhotoImages_MediaPhotoImageBackgrounds_MediaPhotoImage~", + column: x => x.MediaPhotoImageBackgroundId, + principalTable: "MediaPhotoImageBackgrounds", + principalColumn: "Id"); table.ForeignKey( name: "FK_MediaPhotoImages_Media_MediaId", column: x => x.MediaId, @@ -241,7 +265,7 @@ namespace WatchIt.Database.Migrations }); migrationBuilder.CreateTable( - name: "MediaProductionCountrys", + name: "MediaProductionCountries", columns: table => new { MediaId = table.Column(type: "bigint", nullable: false), @@ -249,15 +273,15 @@ namespace WatchIt.Database.Migrations }, constraints: table => { - table.PrimaryKey("PK_MediaProductionCountrys", x => new { x.CountryId, x.MediaId }); + table.PrimaryKey("PK_MediaProductionCountries", x => new { x.CountryId, x.MediaId }); table.ForeignKey( - name: "FK_MediaProductionCountrys_Countries_CountryId", + name: "FK_MediaProductionCountries_Countries_CountryId", column: x => x.CountryId, principalTable: "Countries", principalColumn: "Id", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_MediaProductionCountrys_Media_MediaId", + name: "FK_MediaProductionCountries_Media_MediaId", column: x => x.MediaId, principalTable: "Media", principalColumn: "Id", @@ -620,7 +644,7 @@ namespace WatchIt.Database.Migrations migrationBuilder.InsertData( table: "Accounts", columns: new[] { "Id", "BackgroundPictureId", "Description", "Email", "GenderId", "IsAdmin", "LeftSalt", "Password", "ProfilePictureId", "RightSalt", "Username" }, - values: new object[] { 1L, null, null, "root@watch.it", null, true, "qE]Q^g%tU\"6Uu^GfE:V:", new byte[] { 165, 250, 135, 31, 187, 161, 15, 246, 18, 232, 64, 25, 37, 173, 91, 111, 140, 177, 183, 84, 254, 177, 15, 235, 119, 219, 29, 169, 32, 108, 187, 121, 204, 51, 213, 28, 141, 89, 91, 226, 0, 23, 7, 91, 139, 230, 151, 104, 62, 91, 59, 6, 207, 26, 200, 141, 104, 5, 151, 201, 243, 163, 28, 248 }, null, "T7j)~.#%~ZtOFUZFK,K+", "root" }); + values: new object[] { 1L, null, null, "root@watch.it", null, true, "Y&%]J>6Nc3&5~UUXnNxq", new byte[] { 68, 170, 8, 113, 134, 47, 98, 43, 96, 183, 126, 130, 204, 45, 4, 113, 81, 200, 244, 26, 54, 88, 161, 246, 84, 93, 159, 219, 12, 143, 128, 160, 198, 194, 47, 133, 216, 242, 158, 184, 43, 38, 134, 132, 175, 179, 42, 40, 0, 143, 111, 252, 156, 215, 17, 185, 12, 109, 119, 214, 211, 167, 32, 121 }, null, "MV1jo~o3Oa^;NWb\\Q)t_", "root" }); migrationBuilder.InsertData( table: "Countries", @@ -752,6 +776,12 @@ namespace WatchIt.Database.Migrations column: "Id", unique: true); + migrationBuilder.CreateIndex( + name: "IX_MediaPhotoImageBackgrounds_Id", + table: "MediaPhotoImageBackgrounds", + column: "Id", + unique: true); + migrationBuilder.CreateIndex( name: "IX_MediaPhotoImages_Id", table: "MediaPhotoImages", @@ -763,6 +793,11 @@ namespace WatchIt.Database.Migrations table: "MediaPhotoImages", column: "MediaId"); + migrationBuilder.CreateIndex( + name: "IX_MediaPhotoImages_MediaPhotoImageBackgroundId", + table: "MediaPhotoImages", + column: "MediaPhotoImageBackgroundId"); + migrationBuilder.CreateIndex( name: "IX_MediaPosterImages_Id", table: "MediaPosterImages", @@ -770,8 +805,8 @@ namespace WatchIt.Database.Migrations unique: true); migrationBuilder.CreateIndex( - name: "IX_MediaProductionCountrys_MediaId", - table: "MediaProductionCountrys", + name: "IX_MediaProductionCountries_MediaId", + table: "MediaProductionCountries", column: "MediaId"); migrationBuilder.CreateIndex( @@ -995,7 +1030,7 @@ namespace WatchIt.Database.Migrations name: "MediaMovies"); migrationBuilder.DropTable( - name: "MediaProductionCountrys"); + name: "MediaProductionCountries"); migrationBuilder.DropTable( name: "RatingsMedia"); @@ -1057,6 +1092,9 @@ namespace WatchIt.Database.Migrations migrationBuilder.DropTable( name: "MediaSeries"); + migrationBuilder.DropTable( + name: "MediaPhotoImageBackgrounds"); + migrationBuilder.DropTable( name: "Genders"); diff --git a/WatchIt.Database/WatchIt.Database/Migrations/20240418190404_0001_Initial.Designer.cs b/WatchIt.Database/WatchIt.Database/Migrations/20240603131015_Fix.Designer.cs similarity index 95% rename from WatchIt.Database/WatchIt.Database/Migrations/20240418190404_0001_Initial.Designer.cs rename to WatchIt.Database/WatchIt.Database/Migrations/20240603131015_Fix.Designer.cs index c7d5ee2..8cbfeef 100644 --- a/WatchIt.Database/WatchIt.Database/Migrations/20240418190404_0001_Initial.Designer.cs +++ b/WatchIt.Database/WatchIt.Database/Migrations/20240603131015_Fix.Designer.cs @@ -12,15 +12,15 @@ using WatchIt.Database; namespace WatchIt.Database.Migrations { [DbContext(typeof(DatabaseContext))] - [Migration("20240418190404_0001_Initial")] - partial class _0001_Initial + [Migration("20240603131015_Fix")] + partial class Fix { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("ProductVersion", "8.0.5") .HasAnnotation("Proxies:ChangeTracking", false) .HasAnnotation("Proxies:CheckEquality", false) .HasAnnotation("Proxies:LazyLoading", true) @@ -111,9 +111,9 @@ namespace WatchIt.Database.Migrations Email = "root@watch.it", IsAdmin = true, LastActive = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), - LeftSalt = "qE]Q^g%tU\"6Uu^GfE:V:", - Password = new byte[] { 165, 250, 135, 31, 187, 161, 15, 246, 18, 232, 64, 25, 37, 173, 91, 111, 140, 177, 183, 84, 254, 177, 15, 235, 119, 219, 29, 169, 32, 108, 187, 121, 204, 51, 213, 28, 141, 89, 91, 226, 0, 23, 7, 91, 139, 230, 151, 104, 62, 91, 59, 6, 207, 26, 200, 141, 104, 5, 151, 201, 243, 163, 28, 248 }, - RightSalt = "T7j)~.#%~ZtOFUZFK,K+", + LeftSalt = "@(0PF{b6Ot?HO*:yF5`L", + Password = new byte[] { 254, 122, 19, 59, 187, 100, 174, 87, 55, 108, 14, 10, 123, 186, 129, 243, 145, 136, 152, 220, 72, 170, 196, 93, 54, 88, 192, 115, 128, 76, 133, 9, 181, 99, 181, 8, 102, 123, 197, 251, 85, 167, 146, 28, 116, 249, 118, 87, 146, 8, 194, 238, 127, 19, 33, 28, 14, 222, 218, 170, 74, 40, 223, 232 }, + RightSalt = "=pt,3T0#CfC1[}Zfp{/u", Username = "root" }); }); @@ -253,7 +253,8 @@ namespace WatchIt.Database.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); b.Property("Description") - .HasColumnType("text"); + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); b.Property("Name") .IsRequired() @@ -378,16 +379,6 @@ namespace WatchIt.Database.Migrations .HasMaxLength(-1) .HasColumnType("bytea"); - b.Property("IsMediaBackground") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false); - - b.Property("IsUniversalBackground") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false); - b.Property("MediaId") .HasColumnType("bigint"); @@ -411,6 +402,34 @@ namespace WatchIt.Database.Migrations b.ToTable("MediaPhotoImages"); }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImageBackground", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("FirstGradientColor") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("bytea"); + + b.Property("IsUniversalBackground") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("SecondGradientColor") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("bytea"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("MediaPhotoImageBackgrounds"); + }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPosterImage", b => { b.Property("Id") @@ -452,7 +471,7 @@ namespace WatchIt.Database.Migrations b.HasIndex("MediaId"); - b.ToTable("MediaProductionCountrys"); + b.ToTable("MediaProductionCountries"); }); modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeries", b => @@ -1016,6 +1035,17 @@ namespace WatchIt.Database.Migrations b.Navigation("Media"); }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImageBackground", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaPhotoImage", "MediaPhotoImage") + .WithOne("MediaPhotoImageBackground") + .HasForeignKey("WatchIt.Database.Model.Media.MediaPhotoImageBackground", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaPhotoImage"); + }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaProductionCountry", b => { b.HasOne("WatchIt.Database.Model.Common.Country", "Country") @@ -1302,6 +1332,11 @@ namespace WatchIt.Database.Migrations b.Navigation("ViewCountsMedia"); }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImage", b => + { + b.Navigation("MediaPhotoImageBackground"); + }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPosterImage", b => { b.Navigation("Media") diff --git a/WatchIt.Database/WatchIt.Database/Migrations/20240603131015_Fix.cs b/WatchIt.Database/WatchIt.Database/Migrations/20240603131015_Fix.cs new file mode 100644 index 0000000..8161c07 --- /dev/null +++ b/WatchIt.Database/WatchIt.Database/Migrations/20240603131015_Fix.cs @@ -0,0 +1,87 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace WatchIt.Database.Migrations +{ + /// + public partial class Fix : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_MediaPhotoImages_MediaPhotoImageBackgrounds_Id", + table: "MediaPhotoImages"); + + migrationBuilder.DropForeignKey( + name: "FK_MediaPhotoImages_MediaPhotoImageBackgrounds_MediaPhotoImage~", + table: "MediaPhotoImages"); + + migrationBuilder.DropIndex( + name: "IX_MediaPhotoImages_MediaPhotoImageBackgroundId", + table: "MediaPhotoImages"); + + migrationBuilder.DropColumn( + name: "MediaPhotoImageBackgroundId", + table: "MediaPhotoImages"); + + migrationBuilder.UpdateData( + table: "Accounts", + keyColumn: "Id", + keyValue: 1L, + columns: new[] { "LeftSalt", "Password", "RightSalt" }, + values: new object[] { "@(0PF{b6Ot?HO*:yF5`L", new byte[] { 254, 122, 19, 59, 187, 100, 174, 87, 55, 108, 14, 10, 123, 186, 129, 243, 145, 136, 152, 220, 72, 170, 196, 93, 54, 88, 192, 115, 128, 76, 133, 9, 181, 99, 181, 8, 102, 123, 197, 251, 85, 167, 146, 28, 116, 249, 118, 87, 146, 8, 194, 238, 127, 19, 33, 28, 14, 222, 218, 170, 74, 40, 223, 232 }, "=pt,3T0#CfC1[}Zfp{/u" }); + + migrationBuilder.AddForeignKey( + name: "FK_MediaPhotoImageBackgrounds_MediaPhotoImages_Id", + table: "MediaPhotoImageBackgrounds", + column: "Id", + principalTable: "MediaPhotoImages", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_MediaPhotoImageBackgrounds_MediaPhotoImages_Id", + table: "MediaPhotoImageBackgrounds"); + + migrationBuilder.AddColumn( + name: "MediaPhotoImageBackgroundId", + table: "MediaPhotoImages", + type: "uuid", + nullable: true); + + migrationBuilder.UpdateData( + table: "Accounts", + keyColumn: "Id", + keyValue: 1L, + columns: new[] { "LeftSalt", "Password", "RightSalt" }, + values: new object[] { "Y&%]J>6Nc3&5~UUXnNxq", new byte[] { 68, 170, 8, 113, 134, 47, 98, 43, 96, 183, 126, 130, 204, 45, 4, 113, 81, 200, 244, 26, 54, 88, 161, 246, 84, 93, 159, 219, 12, 143, 128, 160, 198, 194, 47, 133, 216, 242, 158, 184, 43, 38, 134, 132, 175, 179, 42, 40, 0, 143, 111, 252, 156, 215, 17, 185, 12, 109, 119, 214, 211, 167, 32, 121 }, "MV1jo~o3Oa^;NWb\\Q)t_" }); + + migrationBuilder.CreateIndex( + name: "IX_MediaPhotoImages_MediaPhotoImageBackgroundId", + table: "MediaPhotoImages", + column: "MediaPhotoImageBackgroundId"); + + migrationBuilder.AddForeignKey( + name: "FK_MediaPhotoImages_MediaPhotoImageBackgrounds_Id", + table: "MediaPhotoImages", + column: "Id", + principalTable: "MediaPhotoImageBackgrounds", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_MediaPhotoImages_MediaPhotoImageBackgrounds_MediaPhotoImage~", + table: "MediaPhotoImages", + column: "MediaPhotoImageBackgroundId", + principalTable: "MediaPhotoImageBackgrounds", + principalColumn: "Id"); + } + } +} diff --git a/WatchIt.Database/WatchIt.Database/Migrations/DatabaseContextModelSnapshot.cs b/WatchIt.Database/WatchIt.Database/Migrations/DatabaseContextModelSnapshot.cs index 2318c69..dce4d31 100644 --- a/WatchIt.Database/WatchIt.Database/Migrations/DatabaseContextModelSnapshot.cs +++ b/WatchIt.Database/WatchIt.Database/Migrations/DatabaseContextModelSnapshot.cs @@ -17,7 +17,7 @@ namespace WatchIt.Database.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("ProductVersion", "8.0.5") .HasAnnotation("Proxies:ChangeTracking", false) .HasAnnotation("Proxies:CheckEquality", false) .HasAnnotation("Proxies:LazyLoading", true) @@ -108,9 +108,9 @@ namespace WatchIt.Database.Migrations Email = "root@watch.it", IsAdmin = true, LastActive = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), - LeftSalt = "qE]Q^g%tU\"6Uu^GfE:V:", - Password = new byte[] { 165, 250, 135, 31, 187, 161, 15, 246, 18, 232, 64, 25, 37, 173, 91, 111, 140, 177, 183, 84, 254, 177, 15, 235, 119, 219, 29, 169, 32, 108, 187, 121, 204, 51, 213, 28, 141, 89, 91, 226, 0, 23, 7, 91, 139, 230, 151, 104, 62, 91, 59, 6, 207, 26, 200, 141, 104, 5, 151, 201, 243, 163, 28, 248 }, - RightSalt = "T7j)~.#%~ZtOFUZFK,K+", + LeftSalt = "@(0PF{b6Ot?HO*:yF5`L", + Password = new byte[] { 254, 122, 19, 59, 187, 100, 174, 87, 55, 108, 14, 10, 123, 186, 129, 243, 145, 136, 152, 220, 72, 170, 196, 93, 54, 88, 192, 115, 128, 76, 133, 9, 181, 99, 181, 8, 102, 123, 197, 251, 85, 167, 146, 28, 116, 249, 118, 87, 146, 8, 194, 238, 127, 19, 33, 28, 14, 222, 218, 170, 74, 40, 223, 232 }, + RightSalt = "=pt,3T0#CfC1[}Zfp{/u", Username = "root" }); }); @@ -250,7 +250,8 @@ namespace WatchIt.Database.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); b.Property("Description") - .HasColumnType("text"); + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); b.Property("Name") .IsRequired() @@ -375,16 +376,6 @@ namespace WatchIt.Database.Migrations .HasMaxLength(-1) .HasColumnType("bytea"); - b.Property("IsMediaBackground") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false); - - b.Property("IsUniversalBackground") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false); - b.Property("MediaId") .HasColumnType("bigint"); @@ -408,6 +399,34 @@ namespace WatchIt.Database.Migrations b.ToTable("MediaPhotoImages"); }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImageBackground", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("FirstGradientColor") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("bytea"); + + b.Property("IsUniversalBackground") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("SecondGradientColor") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("bytea"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("MediaPhotoImageBackgrounds"); + }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPosterImage", b => { b.Property("Id") @@ -449,7 +468,7 @@ namespace WatchIt.Database.Migrations b.HasIndex("MediaId"); - b.ToTable("MediaProductionCountrys"); + b.ToTable("MediaProductionCountries"); }); modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeries", b => @@ -1013,6 +1032,17 @@ namespace WatchIt.Database.Migrations b.Navigation("Media"); }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImageBackground", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaPhotoImage", "MediaPhotoImage") + .WithOne("MediaPhotoImageBackground") + .HasForeignKey("WatchIt.Database.Model.Media.MediaPhotoImageBackground", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaPhotoImage"); + }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaProductionCountry", b => { b.HasOne("WatchIt.Database.Model.Common.Country", "Country") @@ -1299,6 +1329,11 @@ namespace WatchIt.Database.Migrations b.Navigation("ViewCountsMedia"); }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImage", b => + { + b.Navigation("MediaPhotoImageBackground"); + }); + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPosterImage", b => { b.Navigation("Media") diff --git a/WatchIt.Database/WatchIt.Database/WatchIt.Database.csproj b/WatchIt.Database/WatchIt.Database/WatchIt.Database.csproj index 31e5072..e836832 100644 --- a/WatchIt.Database/WatchIt.Database/WatchIt.Database.csproj +++ b/WatchIt.Database/WatchIt.Database/WatchIt.Database.csproj @@ -7,20 +7,20 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/MediaController.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/MediaController.cs new file mode 100644 index 0000000..09b41d5 --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/MediaController.cs @@ -0,0 +1,83 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WatchIt.Common.Model.Genres; +using WatchIt.Common.Model.Media; +using WatchIt.WebAPI.Services.Controllers.Media; + +namespace WatchIt.WebAPI.Controllers; + +[ApiController] +[Route("media")] +public class MediaController(IMediaControllerService mediaControllerService) +{ + [HttpGet("{id}/genres")] + [AllowAnonymous] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetGenres([FromRoute]long id) => await mediaControllerService.GetGenres(id); + + [HttpPost("{id}/genres/{genre_id}")] + [Authorize] + [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task PostGenre([FromRoute]long id, [FromRoute(Name = "genre_id")]short genreId) => await mediaControllerService.PostGenre(id, genreId); + + [HttpDelete("{id}/genres/{genre_id}")] + [Authorize] + [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task DeleteGenre([FromRoute]long id, [FromRoute(Name = "genre_id")]short genreId) => await mediaControllerService.DeleteGenre(id, genreId); + + [HttpGet("{id}/photos/random_background")] + [AllowAnonymous] + [ProducesResponseType(typeof(MediaPhotoResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetMediaRandomBackgroundPhoto([FromRoute]long id) => await mediaControllerService.GetMediaRandomBackgroundPhoto(id); + + [HttpGet("photos/{photo_id}")] + [AllowAnonymous] + [ProducesResponseType(typeof(MediaPhotoResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetPhoto([FromRoute(Name = "photo_id")] Guid photoId) => await mediaControllerService.GetPhoto(photoId); + + [HttpGet("photos")] + [AllowAnonymous] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetPhotos(MediaPhotoQueryParameters query) => await mediaControllerService.GetPhotos(query); + + [HttpGet("photos/random_background")] + [AllowAnonymous] + [ProducesResponseType(typeof(MediaPhotoResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetRandomBackgroundPhoto() => await mediaControllerService.GetRandomBackgroundPhoto(); + + [HttpPost("photos")] + [Authorize] + [ProducesResponseType(typeof(MediaPhotoResponse), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + public async Task PostPhoto([FromBody]MediaPhotoRequest body) => await mediaControllerService.PostPhoto(body); + + [HttpPut("photos/{photo_id}")] + [Authorize] + [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task PutPhoto([FromRoute(Name = "photo_id")]Guid photoId, [FromBody]MediaPhotoRequest body) => await mediaControllerService.PutPhoto(photoId, body); + + [HttpDelete("photos/{photo_id}")] + [Authorize] + [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task DeletePhoto([FromRoute(Name = "photo_id")]Guid photoId) => await mediaControllerService.DeletePhoto(photoId); +} \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/MoviesController.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/MoviesController.cs index 3d56134..c99f563 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/MoviesController.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/MoviesController.cs @@ -36,33 +36,11 @@ public class MoviesController(IMoviesControllerService moviesControllerService) [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] public async Task Put([FromRoute]long id, [FromBody]MovieRequest body) => await moviesControllerService.Put(id, body); - + [HttpDelete("{id}")] [Authorize] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] - public async Task Delete([FromRoute]long id) => await moviesControllerService.Delete(id); - - [HttpGet("{id}/genres")] - [AllowAnonymous] - [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task GetGenres([FromRoute]long id) => await moviesControllerService.GetGenres(id); - - [HttpPost("{id}/genres/{genre_id}")] - [Authorize] - [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] - [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task PostGenre([FromRoute]long id, [FromRoute(Name = "genre_id")]short genreId) => await moviesControllerService.PostGenre(id, genreId); - - [HttpDelete("{id}/genres/{genre_id}")] - [Authorize] - [ProducesResponseType(typeof(void), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] - [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task DeleteGenre([FromRoute]long id, [FromRoute(Name = "genre_id")]short genreId) => await moviesControllerService.DeleteGenre(id, genreId); + public async Task Delete([FromRoute] long id) => await moviesControllerService.Delete(id); } \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/WatchIt.WebAPI.Controllers.csproj b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/WatchIt.WebAPI.Controllers.csproj index fecaed4..f36d737 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/WatchIt.WebAPI.Controllers.csproj +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/WatchIt.WebAPI.Controllers.csproj @@ -14,6 +14,7 @@ + diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Media/IMediaControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Media/IMediaControllerService.cs new file mode 100644 index 0000000..dd87114 --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Media/IMediaControllerService.cs @@ -0,0 +1,18 @@ +using WatchIt.Common.Model.Media; +using WatchIt.WebAPI.Services.Controllers.Common; + +namespace WatchIt.WebAPI.Services.Controllers.Media; + +public interface IMediaControllerService +{ + Task GetGenres(long mediaId); + Task PostGenre(long mediaId, short genreId); + Task DeleteGenre(long mediaId, short genreId); + Task GetPhoto(Guid id); + Task GetPhotos(MediaPhotoQueryParameters query); + Task GetRandomBackgroundPhoto(); + Task GetMediaRandomBackgroundPhoto(long id); + Task PostPhoto(MediaPhotoRequest data); + Task PutPhoto(Guid photoId, MediaPhotoRequest data); + Task DeletePhoto(Guid photoId); +} \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Media/MediaControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Media/MediaControllerService.cs new file mode 100644 index 0000000..15d5382 --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Media/MediaControllerService.cs @@ -0,0 +1,202 @@ +using Microsoft.EntityFrameworkCore; +using SimpleToolkit.Extensions; +using WatchIt.Common.Model.Genres; +using WatchIt.Common.Model.Media; +using WatchIt.Database; +using WatchIt.Database.Model.Media; +using WatchIt.WebAPI.Services.Controllers.Common; +using WatchIt.WebAPI.Services.Utility.User; + +namespace WatchIt.WebAPI.Services.Controllers.Media; + +public class MediaControllerService(DatabaseContext database, IUserService userService) : IMediaControllerService +{ + #region PUBLIC METHODS + + public async Task GetGenres(long mediaId) + { + MediaMovie? item = await database.MediaMovies.FirstOrDefaultAsync(x => x.Id == mediaId); + if (item is null) + { + return RequestResult.NotFound(); + } + + IEnumerable genres = item.Media.MediaGenres.Select(x => new GenreResponse(x.Genre)); + return RequestResult.Ok(genres); + } + + public async Task PostGenre(long mediaId, short genreId) + { + UserValidator validator = userService.GetValidator().MustBeAdmin(); + if (!validator.IsValid) + { + return RequestResult.Forbidden(); + } + + Database.Model.Media.Media? mediaItem = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); + Database.Model.Common.Genre? genreItem = await database.Genres.FirstOrDefaultAsync(x => x.Id == genreId); + if (mediaItem is null || genreItem is null) + { + return RequestResult.NotFound(); + } + + await database.MediaGenres.AddAsync(new MediaGenre + { + GenreId = genreId, + MediaId = mediaId, + }); + await database.SaveChangesAsync(); + + return RequestResult.Ok(); + } + + public async Task DeleteGenre(long mediaId, short genreId) + { + UserValidator validator = userService.GetValidator().MustBeAdmin(); + if (!validator.IsValid) + { + return RequestResult.Forbidden(); + } + + MediaGenre? item = await database.MediaGenres.FirstOrDefaultAsync(x => x.MediaId == mediaId && x.GenreId == genreId); + if (item is null) + { + return RequestResult.NotFound(); + } + + database.MediaGenres.Attach(item); + database.MediaGenres.Remove(item); + await database.SaveChangesAsync(); + + return RequestResult.Ok(); + } + + public async Task GetPhoto(Guid id) + { + MediaPhotoImage? item = await database.MediaPhotoImages.FirstOrDefaultAsync(x => x.Id == id); + if (item is null) + { + return RequestResult.NotFound(); + } + + MediaPhotoResponse data = new MediaPhotoResponse(item); + return RequestResult.Ok(data); + } + + public async Task GetPhotos(MediaPhotoQueryParameters query) + { + IEnumerable data = await database.MediaPhotoImages.Select(x => new MediaPhotoResponse(x)).ToListAsync(); + data = query.PrepareData(data); + return RequestResult.Ok(data); + } + + public Task GetRandomBackgroundPhoto() + { + MediaPhotoImage? image = database.MediaPhotoImages.Where(x => x.MediaPhotoImageBackground != null && x.MediaPhotoImageBackground.IsUniversalBackground).Random(); + if (image is null) + { + return Task.FromResult(RequestResult.NotFound()); + } + + MediaPhotoResponse data = new MediaPhotoResponse(image); + return Task.FromResult(RequestResult.Ok(data)); + } + + public Task GetMediaRandomBackgroundPhoto(long id) + { + MediaPhotoImage? image = database.MediaPhotoImages.Where(x => x.MediaId == id && x.MediaPhotoImageBackground != null).Random(); + if (image is null) + { + return Task.FromResult(RequestResult.NotFound()); + } + + MediaPhotoResponse data = new MediaPhotoResponse(image); + return Task.FromResult(RequestResult.Ok(data)); + } + + public async Task PostPhoto(MediaPhotoRequest data) + { + UserValidator validator = userService.GetValidator().MustBeAdmin(); + if (!validator.IsValid) + { + return RequestResult.Forbidden(); + } + + MediaPhotoImage item = data.CreateMediaPhotoImage(); + await database.MediaPhotoImages.AddAsync(item); + await database.SaveChangesAsync(); + + MediaPhotoImageBackground? background = data.CreateMediaPhotoImageBackground(item.Id); + if (background is not null) + { + await database.MediaPhotoImageBackgrounds.AddAsync(background); + await database.SaveChangesAsync(); + } + + return RequestResult.Created($"photos/{item.Id}", new MediaPhotoResponse(item)); + } + + public async Task PutPhoto(Guid photoId, MediaPhotoRequest data) + { + UserValidator validator = userService.GetValidator().MustBeAdmin(); + if (!validator.IsValid) + { + return RequestResult.Forbidden(); + } + + MediaPhotoImage? item = await database.MediaPhotoImages.FirstOrDefaultAsync(x => x.Id == photoId); + if (item is null) + { + return RequestResult.NotFound(); + } + + data.UpdateMediaPhotoImage(item); + if (item.MediaPhotoImageBackground is null && data.Background is not null) + { + MediaPhotoImageBackground background = data.CreateMediaPhotoImageBackground(item.Id)!; + await database.MediaPhotoImageBackgrounds.AddAsync(background); + } + else if (item.MediaPhotoImageBackground is not null && data.Background is null) + { + database.MediaPhotoImageBackgrounds.Attach(item.MediaPhotoImageBackground); + database.MediaPhotoImageBackgrounds.Remove(item.MediaPhotoImageBackground); + } + else if (item.MediaPhotoImageBackground is not null && data.Background is not null) + { + data.UpdateMediaPhotoImageBackground(item.MediaPhotoImageBackground); + } + await database.SaveChangesAsync(); + + return RequestResult.Ok(); + } + + public async Task DeletePhoto(Guid photoId) + { + UserValidator validator = userService.GetValidator().MustBeAdmin(); + if (!validator.IsValid) + { + return RequestResult.Forbidden(); + } + + MediaPhotoImage? item = await database.MediaPhotoImages.FirstOrDefaultAsync(x => x.Id == photoId); + if (item is null) + { + return RequestResult.NotFound(); + } + + if (item.MediaPhotoImageBackground is not null) + { + database.MediaPhotoImageBackgrounds.Attach(item.MediaPhotoImageBackground); + database.MediaPhotoImageBackgrounds.Remove(item.MediaPhotoImageBackground); + await database.SaveChangesAsync(); + } + + database.MediaPhotoImages.Attach(item); + database.MediaPhotoImages.Remove(item); + await database.SaveChangesAsync(); + + return RequestResult.Ok(); + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Media/WatchIt.WebAPI.Services.Controllers.Media.csproj b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Media/WatchIt.WebAPI.Services.Controllers.Media.csproj new file mode 100644 index 0000000..6e9f94c --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Media/WatchIt.WebAPI.Services.Controllers.Media.csproj @@ -0,0 +1,21 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Movies/IMoviesControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Movies/IMoviesControllerService.cs index 4304808..173f7e7 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Movies/IMoviesControllerService.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Movies/IMoviesControllerService.cs @@ -10,7 +10,4 @@ public interface IMoviesControllerService Task Post(MovieRequest data); Task Put(long id, MovieRequest data); Task Delete(long id); - Task GetGenres(long movieId); - Task PostGenre(long movieId, short genreId); - Task DeleteGenre(long movieId, short genreId); } \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Movies/MoviesControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Movies/MoviesControllerService.cs index 84bbd3b..e1ac00b 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Movies/MoviesControllerService.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Movies/MoviesControllerService.cs @@ -1,11 +1,9 @@ using Microsoft.EntityFrameworkCore; -using WatchIt.Common.Model.Genres; using WatchIt.Common.Model.Movies; using WatchIt.Database; using WatchIt.Database.Model.Media; using WatchIt.WebAPI.Services.Controllers.Common; using WatchIt.WebAPI.Services.Utility.User; -using Genre = WatchIt.Database.Model.Common.Genre; namespace WatchIt.WebAPI.Services.Controllers.Movies; @@ -110,62 +108,5 @@ public class MoviesControllerService(DatabaseContext database, IUserService user return RequestResult.Ok(); } - public async Task GetGenres(long movieId) - { - MediaMovie? item = await database.MediaMovies.FirstOrDefaultAsync(x => x.Id == movieId); - if (item is null) - { - return RequestResult.NotFound(); - } - - IEnumerable genres = item.Media.MediaGenres.Select(x => new GenreResponse(x.Genre)); - return RequestResult.Ok(genres); - } - - public async Task PostGenre(long movieId, short genreId) - { - UserValidator validator = userService.GetValidator().MustBeAdmin(); - if (!validator.IsValid) - { - return RequestResult.Forbidden(); - } - - MediaMovie? movieItem = await database.MediaMovies.FirstOrDefaultAsync(x => x.Id == movieId); - Genre? genreItem = await database.Genres.FirstOrDefaultAsync(x => x.Id == genreId); - if (movieItem is null || genreItem is null) - { - return RequestResult.NotFound(); - } - - await database.MediaGenres.AddAsync(new MediaGenre - { - GenreId = genreId, - MediaId = movieId, - }); - - return RequestResult.Ok(); - } - - public async Task DeleteGenre(long movieId, short genreId) - { - UserValidator validator = userService.GetValidator().MustBeAdmin(); - if (!validator.IsValid) - { - return RequestResult.Forbidden(); - } - - MediaGenre? item = await database.MediaGenres.FirstOrDefaultAsync(x => x.MediaId == movieId && x.GenreId == genreId); - if (item is null) - { - return RequestResult.NotFound(); - } - - database.MediaGenres.Attach(item); - database.MediaGenres.Remove(item); - await database.SaveChangesAsync(); - - return RequestResult.Ok(); - } - #endregion } \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Validators/Media/MediaPhotoRequestValidator.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Validators/Media/MediaPhotoRequestValidator.cs new file mode 100644 index 0000000..6b0d92d --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Validators/Media/MediaPhotoRequestValidator.cs @@ -0,0 +1,21 @@ +using FluentValidation; +using Microsoft.EntityFrameworkCore.Scaffolding.Metadata; +using WatchIt.Common.Model.Media; +using WatchIt.Database; + +namespace WatchIt.WebAPI.Validators.Media; + +public class MediaPhotoRequestValidator : AbstractValidator +{ + public MediaPhotoRequestValidator(DatabaseContext database) + { + RuleFor(x => x.MediaId).MustBeIn(database.Media, x => x.Id).WithMessage("Media does not exists"); + RuleFor(x => x.Image).NotEmpty(); + RuleFor(x => x.MimeType).Matches(@"\w+/.+").WithMessage("Incorrect mimetype"); + When(x => x.Background is not null, () => + { + RuleFor(x => x.Background!.FirstGradientColor).Must(x => x.Length == 3).WithMessage("First gradient color has to be 3 byte long"); + RuleFor(x => x.Background!.SecondGradientColor).Must(x => x.Length == 3).WithMessage("Second gradient color has to be 3 byte long"); + }); + } +} \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs b/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs index 1bd5391..c09a658 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs @@ -9,6 +9,7 @@ using Microsoft.IdentityModel.Tokens; using WatchIt.Database; using WatchIt.WebAPI.Services.Controllers.Accounts; using WatchIt.WebAPI.Services.Controllers.Genres; +using WatchIt.WebAPI.Services.Controllers.Media; using WatchIt.WebAPI.Services.Controllers.Movies; using WatchIt.WebAPI.Services.Utility.Configuration; using WatchIt.WebAPI.Services.Utility.Tokens; @@ -141,6 +142,7 @@ public static class Program builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(); return builder; } diff --git a/WatchIt.WebAPI/WatchIt.WebAPI/WatchIt.WebAPI.csproj b/WatchIt.WebAPI/WatchIt.WebAPI/WatchIt.WebAPI.csproj index 2cabcac..5c06b61 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI/WatchIt.WebAPI.csproj +++ b/WatchIt.WebAPI/WatchIt.WebAPI/WatchIt.WebAPI.csproj @@ -11,7 +11,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/ConfigurationService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/ConfigurationService.cs new file mode 100644 index 0000000..ea86d69 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/ConfigurationService.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.Configuration; +using WatchIt.Website.Services.Utility.Configuration.Model; + +namespace WatchIt.Website.Services.Utility.Configuration; + +public class ConfigurationService(IConfiguration configuration) : IConfigurationService +{ + #region PROPERTIES + + public ConfigurationData Data => configuration.Get()!; + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/IConfigurationService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/IConfigurationService.cs new file mode 100644 index 0000000..9a39607 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/IConfigurationService.cs @@ -0,0 +1,8 @@ +using WatchIt.Website.Services.Utility.Configuration.Model; + +namespace WatchIt.Website.Services.Utility.Configuration; + +public interface IConfigurationService +{ + ConfigurationData Data { get; } +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Accounts.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Accounts.cs new file mode 100644 index 0000000..aeabaea --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Accounts.cs @@ -0,0 +1,9 @@ +namespace WatchIt.Website.Services.Utility.Configuration.Model; + +public class Accounts +{ + public string Base { get; set; } + public string Register { get; set; } + public string Authenticate { get; set; } + public string AuthenticateRefresh { get; set; } +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/ConfigurationData.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/ConfigurationData.cs new file mode 100644 index 0000000..49de0c9 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/ConfigurationData.cs @@ -0,0 +1,8 @@ +namespace WatchIt.Website.Services.Utility.Configuration.Model; + +public class ConfigurationData +{ + public Logging Logging { get; set; } + public string AllowedHosts { get; set; } + public Endpoints Endpoints { get; set; } +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Endpoints.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Endpoints.cs new file mode 100644 index 0000000..94ed6ee --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Endpoints.cs @@ -0,0 +1,10 @@ +namespace WatchIt.Website.Services.Utility.Configuration.Model; + +public class Endpoints +{ + public string Base { get; set; } + public Accounts Accounts { get; set; } + public Genres Genres { get; set; } + public Movies Movies { get; set; } + public Media Media { get; set; } +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Genres.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Genres.cs new file mode 100644 index 0000000..108e72b --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Genres.cs @@ -0,0 +1,11 @@ +namespace WatchIt.Website.Services.Utility.Configuration.Model; + +public class Genres +{ + public string Base { get; set; } + public string GetAll { get; set; } + public string Get { get; set; } + public string Post { get; set; } + public string Put { get; set; } + public string Delete { get; set; } +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/LogLevel.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/LogLevel.cs new file mode 100644 index 0000000..601ee2d --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/LogLevel.cs @@ -0,0 +1,7 @@ +namespace WatchIt.Website.Services.Utility.Configuration.Model; + +public class LogLevel +{ + public string Default { get; set; } + public string Microsoft_AspNetCore { get; set; } +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Logging.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Logging.cs new file mode 100644 index 0000000..25db637 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Logging.cs @@ -0,0 +1,6 @@ +namespace WatchIt.Website.Services.Utility.Configuration.Model; + +public class Logging +{ + public LogLevel LogLevel { get; set; } +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Media.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Media.cs new file mode 100644 index 0000000..5a576a2 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Media.cs @@ -0,0 +1,16 @@ +namespace WatchIt.Website.Services.Utility.Configuration.Model; + +public class Media +{ + public string Base { get; set; } + public string GetGenres { get; set; } + public string PostGenre { get; set; } + public string DeleteGenre { get; set; } + public string GetPhotoMediaRandomBackground { get; set; } + public string GetPhoto { get; set; } + public string GetPhotos { get; set; } + public string GetPhotoRandomBackground { get; set; } + public string PostPhoto { get; set; } + public string PutPhoto { get; set; } + public string DeletePhoto { get; set; } +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Movies.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Movies.cs new file mode 100644 index 0000000..538793a --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/Model/Movies.cs @@ -0,0 +1,14 @@ +namespace WatchIt.Website.Services.Utility.Configuration.Model; + +public class Movies +{ + public string Base { get; set; } + public string GetAll { get; set; } + public string Get { get; set; } + public string Post { get; set; } + public string Put { get; set; } + public string Delete { get; set; } + public string GetGenres { get; set; } + public string PostGenre { get; set; } + public string DeleteGenre { get; set; } +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/WatchIt.Website.Services.Utility.Configuration.csproj b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/WatchIt.Website.Services.Utility.Configuration.csproj new file mode 100644 index 0000000..d26bd3e --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Configuration/WatchIt.Website.Services.Utility.Configuration.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Accounts/AccountsWebAPIService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Accounts/AccountsWebAPIService.cs new file mode 100644 index 0000000..36948c5 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Accounts/AccountsWebAPIService.cs @@ -0,0 +1,63 @@ +using WatchIt.Common.Model.Accounts; +using WatchIt.Common.Services.HttpClient; +using WatchIt.Website.Services.Utility.Configuration; +using WatchIt.Website.Services.Utility.Configuration.Model; +using WatchIt.Website.Services.WebAPI.Common; + +namespace WatchIt.Website.Services.WebAPI.Accounts; + +public class AccountsWebAPIService(IHttpClientService httpClientService, IConfigurationService configurationService) : BaseWebAPIService(configurationService), IAccountsWebAPIService +{ + #region PUBLIC METHODS + + public async Task Register(RegisterRequest data, Action createdAction, Action> badRequestAction) + { + string url = GetUrl(EndpointsConfiguration.Accounts.Register); + HttpRequest request = new HttpRequest(HttpMethodType.Post, url) + { + Body = data, + }; + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(createdAction) + .RegisterActionFor400BadRequest(badRequestAction) + .ExecuteAction(); + } + + public async Task Authenticate(AuthenticateRequest data, Action successAction, Action> badRequestAction, Action unauthorizedAction) + { + string url = GetUrl(EndpointsConfiguration.Accounts.Authenticate); + HttpRequest request = new HttpRequest(HttpMethodType.Post, url) + { + Body = data, + }; + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor400BadRequest(badRequestAction) + .RegisterActionFor401Unauthorized(unauthorizedAction) + .ExecuteAction(); + } + + public async Task AuthenticateRefresh(Action successAction, Action unauthorizedAction, Action forbiddenAction) + { + string url = GetUrl(EndpointsConfiguration.Accounts.AuthenticateRefresh); + HttpRequest request = new HttpRequest(HttpMethodType.Post, url); + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor401Unauthorized(unauthorizedAction) + .RegisterActionFor403Forbidden(forbiddenAction) + .ExecuteAction(); + } + + #endregion + + + + #region PRIVATE METHODS + + protected override string GetServiceBase() => EndpointsConfiguration.Accounts.Base; + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Accounts/IAccountsWebAPIService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Accounts/IAccountsWebAPIService.cs new file mode 100644 index 0000000..3e39caf --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Accounts/IAccountsWebAPIService.cs @@ -0,0 +1,10 @@ +using WatchIt.Common.Model.Accounts; + +namespace WatchIt.Website.Services.WebAPI.Accounts; + +public interface IAccountsWebAPIService +{ + Task Register(RegisterRequest data, Action createdAction, Action> badRequestAction); + Task Authenticate(AuthenticateRequest data, Action successAction, Action> badRequestAction, Action unauthorizedAction); + Task AuthenticateRefresh(Action successAction, Action unauthorizedAction, Action forbiddenAction); +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Accounts/WatchIt.Website.Services.WebAPI.Accounts.csproj b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Accounts/WatchIt.Website.Services.WebAPI.Accounts.csproj new file mode 100644 index 0000000..ca5168e --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Accounts/WatchIt.Website.Services.WebAPI.Accounts.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + + + + + + + + + + diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Common/BaseWebAPIService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Common/BaseWebAPIService.cs new file mode 100644 index 0000000..9970755 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Common/BaseWebAPIService.cs @@ -0,0 +1,25 @@ +using WatchIt.Website.Services.Utility.Configuration; +using WatchIt.Website.Services.Utility.Configuration.Model; + +namespace WatchIt.Website.Services.WebAPI.Common; + +public abstract class BaseWebAPIService(IConfigurationService configurationService) +{ + #region FIELDS + + protected Endpoints EndpointsConfiguration => configurationService.Data.Endpoints; + + #endregion + + + + #region PRIVATE METHODS + + protected abstract string GetServiceBase(); + + protected string GetUrl(string suffix) => string.Concat(EndpointsConfiguration.Base, GetServiceBase(), suffix); + + protected string GetUrl(string suffix, params object[] format) => string.Concat(EndpointsConfiguration.Base, GetServiceBase(), string.Format(suffix, format)); + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Common/WatchIt.Website.Services.WebAPI.Common.csproj b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Common/WatchIt.Website.Services.WebAPI.Common.csproj new file mode 100644 index 0000000..758e55f --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Common/WatchIt.Website.Services.WebAPI.Common.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Genres/WatchIt.Website.Services.WebAPI.Genres.csproj b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Genres/WatchIt.Website.Services.WebAPI.Genres.csproj new file mode 100644 index 0000000..3a63532 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Genres/WatchIt.Website.Services.WebAPI.Genres.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Media/IMediaWebAPIService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Media/IMediaWebAPIService.cs new file mode 100644 index 0000000..4b589d7 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Media/IMediaWebAPIService.cs @@ -0,0 +1,11 @@ +using WatchIt.Common.Model.Genres; +using WatchIt.Common.Model.Media; + +namespace WatchIt.Website.Services.WebAPI.Media; + +public interface IMediaWebAPIService +{ + Task GetGenres(long mediaId, Action> successAction, Action notFoundAction); + Task PostGenre(long mediaId, long genreId, Action successAction, Action unauthorizedAction, Action forbiddenAction, Action notFoundAction); + Task GetPhotoRandomBackground(Action successAction, Action notFoundAction); +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Media/MediaWebAPIService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Media/MediaWebAPIService.cs new file mode 100644 index 0000000..34f8fe6 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Media/MediaWebAPIService.cs @@ -0,0 +1,61 @@ +using WatchIt.Common.Model.Genres; +using WatchIt.Common.Model.Media; +using WatchIt.Common.Services.HttpClient; +using WatchIt.Website.Services.Utility.Configuration; +using WatchIt.Website.Services.Utility.Configuration.Model; +using WatchIt.Website.Services.WebAPI.Common; + +namespace WatchIt.Website.Services.WebAPI.Media; + +public class MediaWebAPIService(IHttpClientService httpClientService, IConfigurationService configurationService) : BaseWebAPIService(configurationService), IMediaWebAPIService +{ + #region PUBLIC METHODS + + public async Task GetGenres(long mediaId, Action>? successAction = null, Action? notFoundAction = null) + { + string url = GetUrl(EndpointsConfiguration.Media.GetGenres, mediaId); + + HttpRequest request = new HttpRequest(HttpMethodType.Get, url); + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor404NotFound(notFoundAction) + .ExecuteAction(); + } + + public async Task PostGenre(long mediaId, long genreId, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null) + { + string url = GetUrl(EndpointsConfiguration.Media.PostGenre, mediaId, genreId); + + HttpRequest request = new HttpRequest(HttpMethodType.Get, url); + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor401Unauthorized(unauthorizedAction) + .RegisterActionFor403Forbidden(forbiddenAction) + .RegisterActionFor404NotFound(notFoundAction) + .ExecuteAction(); + } + + public async Task GetPhotoRandomBackground(Action? successAction = null, Action? notFoundAction = null) + { + string url = GetUrl(EndpointsConfiguration.Media.GetPhotoRandomBackground); + + HttpRequest request = new HttpRequest(HttpMethodType.Get, url); + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor404NotFound(notFoundAction) + .ExecuteAction(); + } + + #endregion + + + + #region PRIVATE METHODS + + protected override string GetServiceBase() => EndpointsConfiguration.Media.Base; + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Media/WatchIt.Website.Services.WebAPI.Media.csproj b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Media/WatchIt.Website.Services.WebAPI.Media.csproj new file mode 100644 index 0000000..ca5168e --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Media/WatchIt.Website.Services.WebAPI.Media.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + + + + + + + + + + diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Movies/WatchIt.Website.Services.WebAPI.Movies.csproj b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Movies/WatchIt.Website.Services.WebAPI.Movies.csproj new file mode 100644 index 0000000..3a63532 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.WebAPI/WatchIt.Website.Services.WebAPI.Movies/WatchIt.Website.Services.WebAPI.Movies.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/WatchIt.Website/WatchIt.Website/Components/App.razor b/WatchIt.Website/WatchIt.Website/App.razor similarity index 78% rename from WatchIt.Website/WatchIt.Website/Components/App.razor rename to WatchIt.Website/WatchIt.Website/App.razor index b0f6aea..61f6eee 100644 --- a/WatchIt.Website/WatchIt.Website/Components/App.razor +++ b/WatchIt.Website/WatchIt.Website/App.razor @@ -6,8 +6,8 @@ - - + + diff --git a/WatchIt.Website/WatchIt.Website/Components/Layout/MainLayout.razor b/WatchIt.Website/WatchIt.Website/Components/Layout/MainLayout.razor deleted file mode 100644 index df0c2d6..0000000 --- a/WatchIt.Website/WatchIt.Website/Components/Layout/MainLayout.razor +++ /dev/null @@ -1,23 +0,0 @@ -@inherits LayoutComponentBase - -
- - -
-
- About -
- -
- @Body -
-
-
- -
- An unhandled error has occurred. - Reload - 🗙 -
\ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Layout/MainLayout.razor.css b/WatchIt.Website/WatchIt.Website/Components/Layout/MainLayout.razor.css deleted file mode 100644 index 038baf1..0000000 --- a/WatchIt.Website/WatchIt.Website/Components/Layout/MainLayout.razor.css +++ /dev/null @@ -1,96 +0,0 @@ -.page { - position: relative; - display: flex; - flex-direction: column; -} - -main { - flex: 1; -} - -.sidebar { - background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); -} - -.top-row { - background-color: #f7f7f7; - border-bottom: 1px solid #d6d5d5; - justify-content: flex-end; - height: 3.5rem; - display: flex; - align-items: center; -} - - .top-row ::deep a, .top-row ::deep .btn-link { - white-space: nowrap; - margin-left: 1.5rem; - text-decoration: none; - } - - .top-row ::deep a:hover, .top-row ::deep .btn-link:hover { - text-decoration: underline; - } - - .top-row ::deep a:first-child { - overflow: hidden; - text-overflow: ellipsis; - } - -@media (max-width: 640.98px) { - .top-row { - justify-content: space-between; - } - - .top-row ::deep a, .top-row ::deep .btn-link { - margin-left: 0; - } -} - -@media (min-width: 641px) { - .page { - flex-direction: row; - } - - .sidebar { - width: 250px; - height: 100vh; - position: sticky; - top: 0; - } - - .top-row { - position: sticky; - top: 0; - z-index: 1; - } - - .top-row.auth ::deep a:first-child { - flex: 1; - text-align: right; - width: 0; - } - - .top-row, article { - padding-left: 2rem !important; - padding-right: 1.5rem !important; - } -} - -#blazor-error-ui { - background: lightyellow; - bottom: 0; - box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); - display: none; - left: 0; - padding: 0.6rem 1.25rem 0.7rem 1.25rem; - position: fixed; - width: 100%; - z-index: 1000; -} - - #blazor-error-ui .dismiss { - cursor: pointer; - position: absolute; - right: 0.75rem; - top: 0.5rem; - } diff --git a/WatchIt.Website/WatchIt.Website/Components/Layout/NavMenu.razor b/WatchIt.Website/WatchIt.Website/Components/Layout/NavMenu.razor deleted file mode 100644 index 5305774..0000000 --- a/WatchIt.Website/WatchIt.Website/Components/Layout/NavMenu.razor +++ /dev/null @@ -1,29 +0,0 @@ - - - - - \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Layout/NavMenu.razor.css b/WatchIt.Website/WatchIt.Website/Components/Layout/NavMenu.razor.css deleted file mode 100644 index 4e15395..0000000 --- a/WatchIt.Website/WatchIt.Website/Components/Layout/NavMenu.razor.css +++ /dev/null @@ -1,105 +0,0 @@ -.navbar-toggler { - appearance: none; - cursor: pointer; - width: 3.5rem; - height: 2.5rem; - color: white; - position: absolute; - top: 0.5rem; - right: 1rem; - border: 1px solid rgba(255, 255, 255, 0.1); - background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1); -} - -.navbar-toggler:checked { - background-color: rgba(255, 255, 255, 0.5); -} - -.top-row { - height: 3.5rem; - background-color: rgba(0,0,0,0.4); -} - -.navbar-brand { - font-size: 1.1rem; -} - -.bi { - display: inline-block; - position: relative; - width: 1.25rem; - height: 1.25rem; - margin-right: 0.75rem; - top: -1px; - background-size: cover; -} - -.bi-house-door-fill-nav-menu { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E"); -} - -.bi-plus-square-fill-nav-menu { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E"); -} - -.bi-list-nested-nav-menu { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E"); -} - -.nav-item { - font-size: 0.9rem; - padding-bottom: 0.5rem; -} - - .nav-item:first-of-type { - padding-top: 1rem; - } - - .nav-item:last-of-type { - padding-bottom: 1rem; - } - - .nav-item ::deep .nav-link { - color: #d7d7d7; - background: none; - border: none; - border-radius: 4px; - height: 3rem; - display: flex; - align-items: center; - line-height: 3rem; - width: 100%; - } - -.nav-item ::deep a.active { - background-color: rgba(255,255,255,0.37); - color: white; -} - -.nav-item ::deep .nav-link:hover { - background-color: rgba(255,255,255,0.1); - color: white; -} - -.nav-scrollable { - display: none; -} - -.navbar-toggler:checked ~ .nav-scrollable { - display: block; -} - -@media (min-width: 641px) { - .navbar-toggler { - display: none; - } - - .nav-scrollable { - /* Never collapse the sidebar for wide screens */ - display: block; - - /* Allow sidebar to scroll for tall menus */ - height: calc(100vh - 3.5rem); - overflow-y: auto; - } -} diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/Counter.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/Counter.razor deleted file mode 100644 index 372905f..0000000 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/Counter.razor +++ /dev/null @@ -1,19 +0,0 @@ -@page "/counter" - -Counter - -

Counter

- -

Current count: @currentCount

- - - -@code { - private int currentCount = 0; - - private void IncrementCount() - { - currentCount++; - } - -} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/Error.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/Error.razor deleted file mode 100644 index 9d7c6be..0000000 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/Error.razor +++ /dev/null @@ -1,36 +0,0 @@ -@page "/Error" -@using System.Diagnostics - -Error - -

Error.

-

An error occurred while processing your request.

- -@if (ShowRequestId) -{ -

- Request ID: @RequestId -

-} - -

Development Mode

-

- Swapping to Development environment will display more detailed information about the error that occurred. -

-

- The Development environment shouldn't be enabled for deployed applications. - It can result in displaying sensitive information from exceptions to end users. - For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development - and restarting the app. -

- -@code{ - [CascadingParameter] private HttpContext? HttpContext { get; set; } - - private string? RequestId { get; set; } - private bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - - protected override void OnInitialized() => - RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier; - -} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/Home.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/Home.razor deleted file mode 100644 index dfcdf75..0000000 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/Home.razor +++ /dev/null @@ -1,7 +0,0 @@ -@page "/" - -Home - -

Hello, world!

- -Welcome to your new app. \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/Weather.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/Weather.razor deleted file mode 100644 index 570e371..0000000 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/Weather.razor +++ /dev/null @@ -1,66 +0,0 @@ -@page "/weather" - -Weather - -

Weather

- -

This component demonstrates showing data.

- -@if (forecasts == null) -{ -

- Loading... -

-} -else -{ - - - - - - - - - - - @foreach (var forecast in forecasts) - { - - - - - - - } - -
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
-} - -@code { - private WeatherForecast[]? forecasts; - - protected override async Task OnInitializedAsync() - { - // Simulate asynchronous loading to demonstrate a loading indicator - await Task.Delay(500); - - var startDate = DateOnly.FromDateTime(DateTime.Now); - var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; - forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = startDate.AddDays(index), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = summaries[Random.Shared.Next(summaries.Length)] - }).ToArray(); - } - - private class WeatherForecast - { - public DateOnly Date { get; set; } - public int TemperatureC { get; set; } - public string? Summary { get; set; } - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - } - -} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Layout/EmptyLayout.razor b/WatchIt.Website/WatchIt.Website/Layout/EmptyLayout.razor new file mode 100644 index 0000000..53a4e95 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Layout/EmptyLayout.razor @@ -0,0 +1,3 @@ +@inherits LayoutComponentBase + +@Body \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Layout/EmptyLayout.razor.css b/WatchIt.Website/WatchIt.Website/Layout/EmptyLayout.razor.css new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Layout/EmptyLayout.razor.css @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Layout/MainLayout.razor b/WatchIt.Website/WatchIt.Website/Layout/MainLayout.razor new file mode 100644 index 0000000..2b3dc7c --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Layout/MainLayout.razor @@ -0,0 +1,99 @@ +@using System.Diagnostics +@using System.Text +@using WatchIt.Common.Model.Media +@using WatchIt.Website.Services.WebAPI.Media +@inherits LayoutComponentBase + +@if (loaded) +{ +
+
+ +
+

Menu

+
+
+
+ @if (signedIn) + { +

test

+ } + else + { + Sign in or up + } +
+
+
+
+
+ @Body +
+
+
+ + +} + + + + +@code +{ + #region SERVICES + + [Inject] public ILogger Logger { get; set; } = default!; + [Inject] public IMediaWebAPIService MediaWebAPIService { get; set; } = default!; + + #endregion + + + + #region FIELDS + + private bool loaded = false; + + private string background = "assets/background_temp.jpg"; + private string firstGradientColor = "#c6721c"; + private string secondGradientColor = "#85200c"; + private bool signedIn = false; + + #endregion + + + + #region METHODS + + protected override async Task OnInitializedAsync() + { + Action backgroundSuccess = (data) => + { + string imageBase64 = Convert.ToBase64String(data.Image); + string firstColor = BitConverter.ToString(data.Background.FirstGradientColor) + .Replace("-", string.Empty); + string secondColor = BitConverter.ToString(data.Background.SecondGradientColor) + .Replace("-", string.Empty); + + background = $"data:{data.MimeType};base64,{imageBase64}"; + firstGradientColor = $"#{firstColor}"; + secondGradientColor = $"#{secondColor}"; + }; + await MediaWebAPIService.GetPhotoRandomBackground(backgroundSuccess, null); + + loaded = true; + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Layout/MainLayout.razor.css b/WatchIt.Website/WatchIt.Website/Layout/MainLayout.razor.css new file mode 100644 index 0000000..350d80d --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Layout/MainLayout.razor.css @@ -0,0 +1,21 @@ +body { + background-size: cover; +} + +.logo { + font-size: 40px; +} + +.header { + position: sticky; + top: 10px; + height: 60px; +} + +.body-content { + padding-top: 100px; +} + +h1 { + margin: 0; +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Pages/Auth.razor b/WatchIt.Website/WatchIt.Website/Pages/Auth.razor new file mode 100644 index 0000000..ab08b93 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Pages/Auth.razor @@ -0,0 +1,73 @@ +@page "/auth" +@layout EmptyLayout + +WatchIt - @(_authType == AuthType.SignIn ? "Sign in" : "Sign up") + + + + + +
+
+ + @if (_authType == AuthType.SignIn) + { + + } +
+
+ + + + + + + + + + + +@code { + + #region ENUMS + + private enum AuthType + { + SignIn, + SignUp + } + + #endregion + + + + #region FIELDS + + private AuthType _authType = AuthType.SignIn; + private string _background = "assets/background_temp.jpg"; + private string _firstGradientColor = "#c6721c"; + private string _secondGradientColor = "#85200c"; + + #endregion + + + + #region METHODS + + protected override Task OnInitializedAsync() + { + return base.OnInitializedAsync(); + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Pages/Auth.razor.css b/WatchIt.Website/WatchIt.Website/Pages/Auth.razor.css new file mode 100644 index 0000000..93f6b3c --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Pages/Auth.razor.css @@ -0,0 +1,8 @@ +body { + background-size: cover; +} + +.logo { + font-size: 60px; + margin: 10px; +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Pages/Home.razor b/WatchIt.Website/WatchIt.Website/Pages/Home.razor new file mode 100644 index 0000000..f68e886 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Pages/Home.razor @@ -0,0 +1,50 @@ +@page "/" + +WatchIt + +
+
+
+

Hello, world!

+ + Welcome to your new app. + + +

Hello, world!

+ + Welcome to your new app. + + +

Hello, world!

+ + Welcome to your new app. + +

Hello, world!

+ + Welcome to your new app. +

Hello, world!

+ + Welcome to your new app. +

Hello, world!

+ + Welcome to your new app. +

Hello, world!

+ + Welcome to your new app. +

Hello, world!

+ + Welcome to your new app. +

Hello, world!

+ + Welcome to your new app. +

Hello, world!

+ + Welcome to your new app. + + +

Hello, world!

+ + Welcome to your new app. +
+
+
\ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Program.cs b/WatchIt.Website/WatchIt.Website/Program.cs index 63d2902..e3647e1 100644 --- a/WatchIt.Website/WatchIt.Website/Program.cs +++ b/WatchIt.Website/WatchIt.Website/Program.cs @@ -1,18 +1,20 @@ -using WatchIt.Website.Components; +using WatchIt.Common.Services.HttpClient; +using WatchIt.Website.Services.Utility.Configuration; +using WatchIt.Website.Services.WebAPI.Accounts; +using WatchIt.Website.Services.WebAPI.Media; namespace WatchIt.Website; -public class Program +public static class Program { + #region PUBLIC METHODS + public static void Main(string[] args) { - var builder = WebApplication.CreateBuilder(args); - - // Add services to the container. - builder.Services.AddRazorComponents() - .AddInteractiveServerComponents(); - - var app = builder.Build(); + WebApplication app = WebApplication.CreateBuilder(args) + .SetupServices() + .SetupApplication() + .Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) @@ -32,4 +34,34 @@ public class Program app.Run(); } + + #endregion + + + + #region PRIVATE METHODS + + private static WebApplicationBuilder SetupServices(this WebApplicationBuilder builder) + { + builder.Services.AddHttpClient(); + + // Utility + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + + // WebAPI + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + + return builder; + } + + private static WebApplicationBuilder SetupApplication(this WebApplicationBuilder builder) + { + builder.Services.AddRazorComponents() + .AddInteractiveServerComponents(); + return builder; + } + + #endregion } \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Routes.razor b/WatchIt.Website/WatchIt.Website/Routes.razor similarity index 100% rename from WatchIt.Website/WatchIt.Website/Components/Routes.razor rename to WatchIt.Website/WatchIt.Website/Routes.razor diff --git a/WatchIt.Website/WatchIt.Website/WatchIt.Website.csproj b/WatchIt.Website/WatchIt.Website/WatchIt.Website.csproj index 6012379..68af502 100644 --- a/WatchIt.Website/WatchIt.Website/WatchIt.Website.csproj +++ b/WatchIt.Website/WatchIt.Website/WatchIt.Website.csproj @@ -13,4 +13,30 @@ + + + + + + + + + <_ContentIncludedByDefault Remove="Components\Layout\EmptyLayout.razor" /> + <_ContentIncludedByDefault Remove="Components\Layout\MainLayout.razor" /> + <_ContentIncludedByDefault Remove="Components\Pages\Counter.razor" /> + <_ContentIncludedByDefault Remove="Components\Pages\Error.razor" /> + <_ContentIncludedByDefault Remove="Components\Pages\Home.razor" /> + <_ContentIncludedByDefault Remove="Components\Pages\Weather.razor" /> + + + + + + + + + + + + diff --git a/WatchIt.Website/WatchIt.Website/Components/_Imports.razor b/WatchIt.Website/WatchIt.Website/_Imports.razor similarity index 91% rename from WatchIt.Website/WatchIt.Website/Components/_Imports.razor rename to WatchIt.Website/WatchIt.Website/_Imports.razor index 6433b1a..60530df 100644 --- a/WatchIt.Website/WatchIt.Website/Components/_Imports.razor +++ b/WatchIt.Website/WatchIt.Website/_Imports.razor @@ -7,4 +7,4 @@ @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using WatchIt.Website -@using WatchIt.Website.Components \ No newline at end of file +@using WatchIt.Website.Layout \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/appsettings.json b/WatchIt.Website/WatchIt.Website/appsettings.json index 10f68b8..47244bc 100644 --- a/WatchIt.Website/WatchIt.Website/appsettings.json +++ b/WatchIt.Website/WatchIt.Website/appsettings.json @@ -5,5 +5,46 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "Endpoints": { + "Base": "https://localhost:7160", + "Accounts": { + "Base": "/accounts", + "Register": "/register", + "Authenticate": "/authenticate", + "AuthenticateRefresh": "/authenticate-refresh" + }, + "Genres": { + "Base": "/genres", + "GetAll": "", + "Get": "/{0}", + "Post": "", + "Put": "/{0}", + "Delete": "/{0}" + }, + "Movies": { + "Base": "/movies", + "GetAll": "", + "Get": "/{0}", + "Post": "", + "Put": "/{0}", + "Delete": "/{0}", + "GetGenres": "/{0}/genres", + "PostGenre": "{0}/genres/{1}", + "DeleteGenre": "{0}/genres/{1}" + }, + "Media": { + "Base": "/media", + "GetGenres": "/{0}/genres", + "PostGenre": "/{0}/genres/{1}", + "DeleteGenre": "/{0}/genres/{1}", + "GetPhotoMediaRandomBackground": "/{0}/photos/random_background", + "GetPhoto": "/photos/{0}", + "GetPhotos": "/photos", + "GetPhotoRandomBackground": "/photos/random_background", + "PostPhoto": "/photos", + "PutPhoto": "/photos/{0}", + "DeletePhoto": "/photos/{0}" + } + } } diff --git a/WatchIt.Website/WatchIt.Website/wwwroot/app.css b/WatchIt.Website/WatchIt.Website/wwwroot/app.css index 2bd9b78..09abd8f 100644 --- a/WatchIt.Website/WatchIt.Website/wwwroot/app.css +++ b/WatchIt.Website/WatchIt.Website/wwwroot/app.css @@ -1,51 +1,80 @@ -html, body { - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; +@font-face { + font-family: Belanosima; + src: url(fonts/Belanosima-Regular.ttf) format('truetype'); } -a, .btn-link { - color: #006bb7; +@font-face { + font-family: Belanosima; + src: url(fonts/Belanosima-Bold.ttf) format('truetype'); + font-weight: bold; } -.btn-primary { +body, html { + background-color: transparent; + height: 100%; + margin: 0; + padding: 0; +} + +.logo { + font-family: Belanosima; + text-decoration: none; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.panel { + background-color: rgba(0, 0, 0, 0.8); + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + backdrop-filter: blur(25px); + z-index: 1000; +} + +.main-button { + --r:10px; + --b:2px; + + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + color: transparent; + padding: 5px 10px; + + border-radius: var(--r); + display: block; + align-items: self-end; + position: relative; + z-index:0; + text-decoration: none; + transition: 0.3s; + font-family: Belanosima; +} + +.main-button::before { + content:""; + position:absolute; + z-index:-1; + inset: 0; + border: var(--b) solid transparent; + border-radius: var(--r); + background: inherit; + background-origin: border-box; + background-clip: border-box; + -webkit-mask: + linear-gradient(#fff 0 0) padding-box, + linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + -webkit-mask-repeat: no-repeat; +} + +.main-button:hover { color: #fff; - background-color: #1b6ec2; - border-color: #1861ac; + -webkit-text-fill-color: #fff; + -webkit-background-clip: border-box; + background-clip: border-box; } -.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus { - box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb; -} - -.content { - padding-top: 1.1rem; -} - -h1:focus { - outline: none; -} - -.valid.modified:not([type=checkbox]) { - outline: 1px solid #26b050; -} - -.invalid { - outline: 1px solid #e50000; -} - -.validation-message { - color: #e50000; -} - -.blazor-error-boundary { - background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; - padding: 1rem 1rem 1rem 3.7rem; - color: white; -} - - .blazor-error-boundary::after { - content: "An error has occurred." - } - -.darker-border-checkbox.form-check-input { - border-color: #929292; -} +.main-button:hover::before { + -webkit-mask:none; +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/wwwroot/assets/background_temp.jpg b/WatchIt.Website/WatchIt.Website/wwwroot/assets/background_temp.jpg new file mode 100644 index 0000000..d0e86ce Binary files /dev/null and b/WatchIt.Website/WatchIt.Website/wwwroot/assets/background_temp.jpg differ diff --git a/WatchIt.Website/WatchIt.Website/wwwroot/fonts/Belanosima-Bold.ttf b/WatchIt.Website/WatchIt.Website/wwwroot/fonts/Belanosima-Bold.ttf new file mode 100644 index 0000000..9e2bdb9 Binary files /dev/null and b/WatchIt.Website/WatchIt.Website/wwwroot/fonts/Belanosima-Bold.ttf differ diff --git a/WatchIt.Website/WatchIt.Website/wwwroot/fonts/Belanosima-Regular.ttf b/WatchIt.Website/WatchIt.Website/wwwroot/fonts/Belanosima-Regular.ttf new file mode 100644 index 0000000..2a0f189 Binary files /dev/null and b/WatchIt.Website/WatchIt.Website/wwwroot/fonts/Belanosima-Regular.ttf differ diff --git a/WatchIt.Website/WatchIt.Website/wwwroot/fonts/Belanosima-SemiBold.ttf b/WatchIt.Website/WatchIt.Website/wwwroot/fonts/Belanosima-SemiBold.ttf new file mode 100644 index 0000000..317f0a8 Binary files /dev/null and b/WatchIt.Website/WatchIt.Website/wwwroot/fonts/Belanosima-SemiBold.ttf differ diff --git a/WatchIt.sln b/WatchIt.sln index 09ee577..863c78e 100644 --- a/WatchIt.sln +++ b/WatchIt.sln @@ -50,6 +50,32 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.Website", "WatchIt. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.WebAPI.Services.Controllers.Movies", "WatchIt.WebAPI\WatchIt.WebAPI.Services\WatchIt.WebAPI.Services.Controllers\WatchIt.WebAPI.Services.Controllers.Movies\WatchIt.WebAPI.Services.Controllers.Movies.csproj", "{69BB6A9E-B673-42AB-A516-6B2513E21FDC}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WatchIt.Website.Services", "WatchIt.Website.Services", "{A82972D0-9A60-4B3F-AE46-9F304D79137F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WatchIt.Website.Services.WebAPI", "WatchIt.Website.Services.WebAPI", "{46E3711F-18BD-4004-AF53-EA4D8643D92F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.Website.Services.WebAPI.Accounts", "WatchIt.Website\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Accounts\WatchIt.Website.Services.WebAPI.Accounts.csproj", "{68B7E892-9074-4034-8AFC-2474D7D5BE29}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.Website.Services.WebAPI.Genres", "WatchIt.Website\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Genres\WatchIt.Website.Services.WebAPI.Genres.csproj", "{A98D06A6-9C95-4449-9F4E-1D31BBE1D9B1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.Website.Services.WebAPI.Movies", "WatchIt.Website\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Movies\WatchIt.Website.Services.WebAPI.Movies.csproj", "{539404EB-BDFD-46F8-8F21-6A231ABED9B1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WatchIt.Website.Services.Utility", "WatchIt.Website.Services.Utility", "{130BC8F5-82CE-4EDF-AECB-21594DD41849}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WatchIt.Common.Services", "WatchIt.Common.Services", "{882A9795-4AC0-4556-9750-6582B2701EFA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.Common.Query", "WatchIt.Common\WatchIt.Common.Query\WatchIt.Common.Query.csproj", "{6C3AE7B4-18C5-42D3-B254-460027E50143}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.Common.Services.HttpClient", "WatchIt.Common\WatchIt.Common.Services\WatchIt.Common.Services.HttpClient\WatchIt.Common.Services.HttpClient.csproj", "{A4A75CCA-0DEE-4F1E-9816-60674CA807FA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.Website.Services.Utility.Configuration", "WatchIt.Website\WatchIt.Website.Services\WatchIt.Website.Services.Utility\WatchIt.Website.Services.Utility.Configuration\WatchIt.Website.Services.Utility.Configuration.csproj", "{0DBBE7EA-05FE-481F-8814-6FA0BC9E571F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.WebAPI.Services.Controllers.Media", "WatchIt.WebAPI\WatchIt.WebAPI.Services\WatchIt.WebAPI.Services.Controllers\WatchIt.WebAPI.Services.Controllers.Media\WatchIt.WebAPI.Services.Controllers.Media.csproj", "{3156AD7B-D6EC-4EB6-AEE8-4FBAF14C18E4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.Website.Services.WebAPI.Media", "WatchIt.Website\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Media\WatchIt.Website.Services.WebAPI.Media.csproj", "{1D64B7B5-650D-4AF3-AC33-A8D1F0999906}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.Website.Services.WebAPI.Common", "WatchIt.Website\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Common\WatchIt.Website.Services.WebAPI.Common.csproj", "{2D62ED42-489E-4888-9479-E5A50A0E7D70}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -77,6 +103,19 @@ Global {2EC6FD28-C580-45FA-B6A7-92A6BF0CCC54} = {CEC468DB-CC49-47D3-9E3E-1CC9530C3CE7} {46CE78A1-3EC3-4112-AAAD-26EEB8D8B194} = {4CB91BF6-87F1-4088-A943-62548CD1F9F4} {69BB6A9E-B673-42AB-A516-6B2513E21FDC} = {CEC468DB-CC49-47D3-9E3E-1CC9530C3CE7} + {A82972D0-9A60-4B3F-AE46-9F304D79137F} = {4CB91BF6-87F1-4088-A943-62548CD1F9F4} + {46E3711F-18BD-4004-AF53-EA4D8643D92F} = {A82972D0-9A60-4B3F-AE46-9F304D79137F} + {68B7E892-9074-4034-8AFC-2474D7D5BE29} = {46E3711F-18BD-4004-AF53-EA4D8643D92F} + {A98D06A6-9C95-4449-9F4E-1D31BBE1D9B1} = {46E3711F-18BD-4004-AF53-EA4D8643D92F} + {539404EB-BDFD-46F8-8F21-6A231ABED9B1} = {46E3711F-18BD-4004-AF53-EA4D8643D92F} + {130BC8F5-82CE-4EDF-AECB-21594DD41849} = {A82972D0-9A60-4B3F-AE46-9F304D79137F} + {882A9795-4AC0-4556-9750-6582B2701EFA} = {E98C42C1-26E5-4939-8C22-72C253DE874B} + {6C3AE7B4-18C5-42D3-B254-460027E50143} = {E98C42C1-26E5-4939-8C22-72C253DE874B} + {A4A75CCA-0DEE-4F1E-9816-60674CA807FA} = {882A9795-4AC0-4556-9750-6582B2701EFA} + {0DBBE7EA-05FE-481F-8814-6FA0BC9E571F} = {130BC8F5-82CE-4EDF-AECB-21594DD41849} + {3156AD7B-D6EC-4EB6-AEE8-4FBAF14C18E4} = {CEC468DB-CC49-47D3-9E3E-1CC9530C3CE7} + {1D64B7B5-650D-4AF3-AC33-A8D1F0999906} = {46E3711F-18BD-4004-AF53-EA4D8643D92F} + {2D62ED42-489E-4888-9479-E5A50A0E7D70} = {46E3711F-18BD-4004-AF53-EA4D8643D92F} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {23383776-1F27-4B5D-8C7C-57BFF75FA473}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -147,5 +186,41 @@ Global {69BB6A9E-B673-42AB-A516-6B2513E21FDC}.Debug|Any CPU.Build.0 = Debug|Any CPU {69BB6A9E-B673-42AB-A516-6B2513E21FDC}.Release|Any CPU.ActiveCfg = Release|Any CPU {69BB6A9E-B673-42AB-A516-6B2513E21FDC}.Release|Any CPU.Build.0 = Release|Any CPU + {68B7E892-9074-4034-8AFC-2474D7D5BE29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68B7E892-9074-4034-8AFC-2474D7D5BE29}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68B7E892-9074-4034-8AFC-2474D7D5BE29}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68B7E892-9074-4034-8AFC-2474D7D5BE29}.Release|Any CPU.Build.0 = Release|Any CPU + {A98D06A6-9C95-4449-9F4E-1D31BBE1D9B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A98D06A6-9C95-4449-9F4E-1D31BBE1D9B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A98D06A6-9C95-4449-9F4E-1D31BBE1D9B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A98D06A6-9C95-4449-9F4E-1D31BBE1D9B1}.Release|Any CPU.Build.0 = Release|Any CPU + {539404EB-BDFD-46F8-8F21-6A231ABED9B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {539404EB-BDFD-46F8-8F21-6A231ABED9B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {539404EB-BDFD-46F8-8F21-6A231ABED9B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {539404EB-BDFD-46F8-8F21-6A231ABED9B1}.Release|Any CPU.Build.0 = Release|Any CPU + {6C3AE7B4-18C5-42D3-B254-460027E50143}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C3AE7B4-18C5-42D3-B254-460027E50143}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C3AE7B4-18C5-42D3-B254-460027E50143}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C3AE7B4-18C5-42D3-B254-460027E50143}.Release|Any CPU.Build.0 = Release|Any CPU + {A4A75CCA-0DEE-4F1E-9816-60674CA807FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4A75CCA-0DEE-4F1E-9816-60674CA807FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4A75CCA-0DEE-4F1E-9816-60674CA807FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4A75CCA-0DEE-4F1E-9816-60674CA807FA}.Release|Any CPU.Build.0 = Release|Any CPU + {0DBBE7EA-05FE-481F-8814-6FA0BC9E571F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DBBE7EA-05FE-481F-8814-6FA0BC9E571F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DBBE7EA-05FE-481F-8814-6FA0BC9E571F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DBBE7EA-05FE-481F-8814-6FA0BC9E571F}.Release|Any CPU.Build.0 = Release|Any CPU + {3156AD7B-D6EC-4EB6-AEE8-4FBAF14C18E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3156AD7B-D6EC-4EB6-AEE8-4FBAF14C18E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3156AD7B-D6EC-4EB6-AEE8-4FBAF14C18E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3156AD7B-D6EC-4EB6-AEE8-4FBAF14C18E4}.Release|Any CPU.Build.0 = Release|Any CPU + {1D64B7B5-650D-4AF3-AC33-A8D1F0999906}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1D64B7B5-650D-4AF3-AC33-A8D1F0999906}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1D64B7B5-650D-4AF3-AC33-A8D1F0999906}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1D64B7B5-650D-4AF3-AC33-A8D1F0999906}.Release|Any CPU.Build.0 = Release|Any CPU + {2D62ED42-489E-4888-9479-E5A50A0E7D70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D62ED42-489E-4888-9479-E5A50A0E7D70}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D62ED42-489E-4888-9479-E5A50A0E7D70}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D62ED42-489E-4888-9479-E5A50A0E7D70}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal