diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.WorkerServices/DeleteExpiredRefreshTokensService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.WorkerServices/DeleteExpiredRefreshTokensService.cs index 7c43b54..00c8d99 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.WorkerServices/DeleteExpiredRefreshTokensService.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.WorkerServices/DeleteExpiredRefreshTokensService.cs @@ -1,3 +1,4 @@ +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using WatchIt.Database; @@ -5,13 +6,36 @@ using WatchIt.Database.Model.Account; namespace WatchIt.WebAPI.WorkerServices; -public class DeleteExpiredRefreshTokensService(ILogger logger, DatabaseContext database) : BackgroundService +public class DeleteExpiredRefreshTokensService : BackgroundService { + #region SERVICES + + private readonly ILogger _logger; + private readonly IServiceScopeFactory _serviceScopeFactory; + + #endregion + + + + #region CONSTRUCTORS + + public DeleteExpiredRefreshTokensService(ILogger logger, IServiceScopeFactory serviceScopeFactory) + { + _logger = logger; + _serviceScopeFactory = serviceScopeFactory; + } + + #endregion + + + + #region PUBLIC METHODS + protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { - logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); + _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); Task delayTask = Task.Delay(300000, stoppingToken); Task actionTask = Action(); @@ -22,9 +46,16 @@ public class DeleteExpiredRefreshTokensService(ILogger tokens = database.AccountRefreshTokens.Where(x => x.ExpirationDate < DateTime.UtcNow); - database.AccountRefreshTokens.AttachRange(tokens); - database.AccountRefreshTokens.RemoveRange(tokens); - await database.SaveChangesAsync(); + using (IServiceScope scope = _serviceScopeFactory.CreateScope()) + { + DatabaseContext database = scope.ServiceProvider.GetService(); + + IEnumerable tokens = database.AccountRefreshTokens.Where(x => x.ExpirationDate < DateTime.UtcNow); + database.AccountRefreshTokens.AttachRange(tokens); + database.AccountRefreshTokens.RemoveRange(tokens); + await database.SaveChangesAsync(); + } } + + #endregion } \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs b/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs index c09a658..212d435 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs @@ -121,7 +121,7 @@ public static class Program private static WebApplicationBuilder SetupDatabase(this WebApplicationBuilder builder) { - builder.Services.AddDbContext(x => x.UseLazyLoadingProxies().UseNpgsql(builder.Configuration.GetConnectionString("Default")), ServiceLifetime.Singleton); + builder.Services.AddDbContext(x => x.UseLazyLoadingProxies().UseNpgsql(builder.Configuration.GetConnectionString("Default")), ServiceLifetime.Transient); return builder; } @@ -134,15 +134,15 @@ public static class Program private static WebApplicationBuilder SetupServices(this WebApplicationBuilder builder) { // Utility - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); // Controller - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); return builder; } diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Authentication/JWTAuthenticationStateProvider.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Authentication/JWTAuthenticationStateProvider.cs index 8e46e30..3646136 100644 --- a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Authentication/JWTAuthenticationStateProvider.cs +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Utility/WatchIt.Website.Services.Utility.Authentication/JWTAuthenticationStateProvider.cs @@ -113,8 +113,13 @@ public class JWTAuthenticationStateProvider : AuthenticationStateProvider private async Task Refresh(string refreshToken) { AuthenticateResponse? response = null; + + void SetResponse(AuthenticateResponse data) + { + response = data; + } - await _accountsService.AuthenticateRefresh((data) => response = data); + await _accountsService.AuthenticateRefresh(SetResponse); if (response is not null) { @@ -151,8 +156,9 @@ public class JWTAuthenticationStateProvider : AuthenticationStateProvider public static DateTime ConvertFromUnixTimestamp(int timestamp) { - DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0); - return origin.AddSeconds(timestamp); + DateTime date = new DateTime(1970, 1, 1, 0, 0, 0, 0); + date = date.AddSeconds(timestamp); + return date; } #endregion diff --git a/WatchIt.Website/WatchIt.Website/App.razor b/WatchIt.Website/WatchIt.Website/App.razor index 50e5622..eb24a1c 100644 --- a/WatchIt.Website/WatchIt.Website/App.razor +++ b/WatchIt.Website/WatchIt.Website/App.razor @@ -9,8 +9,8 @@ - - + + @@ -25,8 +25,8 @@ - - + + \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/MediaForm.razor.css b/WatchIt.Website/WatchIt.Website/Components/MediaForm.razor.css deleted file mode 100644 index 06d4c28..0000000 --- a/WatchIt.Website/WatchIt.Website/Components/MediaForm.razor.css +++ /dev/null @@ -1,3 +0,0 @@ -#posterInput { - width: 300px; -} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/MediaForm.razor b/WatchIt.Website/WatchIt.Website/Components/MediaFormComponent.razor similarity index 65% rename from WatchIt.Website/WatchIt.Website/Components/MediaForm.razor rename to WatchIt.Website/WatchIt.Website/Components/MediaFormComponent.razor index 231d622..f1e87af 100644 --- a/WatchIt.Website/WatchIt.Website/Components/MediaForm.razor +++ b/WatchIt.Website/WatchIt.Website/Components/MediaFormComponent.razor @@ -4,22 +4,36 @@
- @if (_posterChanged) + @if (_posterChanged || !string.IsNullOrWhiteSpace(_actualPosterBase64)) { -
-
- - +
+
+ @if (_posterChanged) + { +
+ +
+
+ +
+ } + else if (!string.IsNullOrWhiteSpace(_actualPosterBase64)) + { +
+ +
+ } + @if (_posterLoading) + { +
+
+
+
+
+ }
} - else - { - if (!string.IsNullOrWhiteSpace(_actualPosterBase64)) - { - - } - }
@@ -73,6 +87,8 @@
+ + -} - - - - - -@code -{ - #region SERVICES - - [Inject] public ILogger Logger { get; set; } = default!; - [Inject] public IAuthenticationService AuthenticationService { get; set; } = default!; - [Inject] public ITokensService TokensService { get; set; } = default!; - [Inject] public IMediaWebAPIService MediaWebAPIService { get; set; } = default!; - [Inject] public IAccountsWebAPIService AccountsWebAPIService { get; set; } = default!; - [Inject] public NavigationManager NavigationManager { get; set; } = default!; - - #endregion - - - - #region ENUMS - - private enum AuthType - { - SignIn, - SignUp - } - - #endregion - - - - #region FIELDS - - private bool _loaded = false; - - private AuthType _authType = AuthType.SignIn; - private string _background = "assets/background_temp.jpg"; - private string _firstGradientColor = "#c6721c"; - private string _secondGradientColor = "#85200c"; - - private AuthenticateRequest _loginModel = new AuthenticateRequest - { - UsernameOrEmail = null, - Password = null - }; - - private RegisterRequest _registerModel = new RegisterRequest - { - Username = null, - Email = null, - Password = null - }; - private string _passwordConfirmation; - - private IEnumerable _errors; - - #endregion - - - - #region METHODS - - protected override async Task OnInitializedAsync() - { - if (await AuthenticationService.GetAuthenticationStatusAsync()) - { - NavigationManager.NavigateTo("/"); - } - - 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); - - _loaded = true; - } - - private async Task Login() - { - await AccountsWebAPIService.Authenticate(_loginModel, LoginSuccess, LoginBadRequest, LoginUnauthorized); - - async void LoginSuccess(AuthenticateResponse data) - { - await TokensService.SaveAuthenticationData(data); - NavigationManager.NavigateTo("/"); - } - - void LoginBadRequest(IDictionary data) - { - _errors = data.SelectMany(x => x.Value).Select(x => $"• {x}"); - } - - void LoginUnauthorized() - { - _errors = [ "Incorrect account data" ]; - } - } - - private async Task Register() - { - if (_registerModel.Password != _passwordConfirmation) - { - _errors = [ "Password fields don't match" ]; - return; - } - - await AccountsWebAPIService.Register(_registerModel, RegisterSuccess, RegisterBadRequest); - - void RegisterSuccess(RegisterResponse data) - { - _authType = AuthType.SignIn; - } - - void RegisterBadRequest(IDictionary data) - { - _errors = data.SelectMany(x => x.Value).Select(x => $"• {x}"); - } - } - - #endregion } \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Pages/AuthPage.razor.cs b/WatchIt.Website/WatchIt.Website/Pages/AuthPage.razor.cs new file mode 100644 index 0000000..b58b7e0 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Pages/AuthPage.razor.cs @@ -0,0 +1,136 @@ +using Microsoft.AspNetCore.Components; +using WatchIt.Common.Model.Accounts; +using WatchIt.Common.Model.Media; +using WatchIt.Website.Services.Utility.Authentication; +using WatchIt.Website.Services.Utility.Tokens; +using WatchIt.Website.Services.WebAPI.Accounts; +using WatchIt.Website.Services.WebAPI.Media; + +namespace WatchIt.Website.Pages; + +public partial class AuthPage +{ + #region SERVICES + + [Inject] public ILogger Logger { get; set; } = default!; + [Inject] public IAuthenticationService AuthenticationService { get; set; } = default!; + [Inject] public ITokensService TokensService { get; set; } = default!; + [Inject] public IMediaWebAPIService MediaWebAPIService { get; set; } = default!; + [Inject] public IAccountsWebAPIService AccountsWebAPIService { get; set; } = default!; + [Inject] public NavigationManager NavigationManager { get; set; } = default!; + + #endregion + + + + #region ENUMS + + private enum AuthType + { + SignIn, + SignUp + } + + #endregion + + + + #region FIELDS + + private bool _loaded = false; + + private AuthType _authType = AuthType.SignIn; + private string _background = "assets/background_temp.jpg"; + private string _firstGradientColor = "#c6721c"; + private string _secondGradientColor = "#85200c"; + + private AuthenticateRequest _loginModel = new AuthenticateRequest + { + UsernameOrEmail = null, + Password = null + }; + + private RegisterRequest _registerModel = new RegisterRequest + { + Username = null, + Email = null, + Password = null + }; + private string _passwordConfirmation; + + private IEnumerable _errors; + + #endregion + + + + #region METHODS + + protected override async Task OnInitializedAsync() + { + if (await AuthenticationService.GetAuthenticationStatusAsync()) + { + NavigationManager.NavigateTo("/"); + } + + 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); + + _loaded = true; + } + + private async Task Login() + { + await AccountsWebAPIService.Authenticate(_loginModel, LoginSuccess, LoginBadRequest, LoginUnauthorized); + + async void LoginSuccess(AuthenticateResponse data) + { + await TokensService.SaveAuthenticationData(data); + NavigationManager.NavigateTo("/"); + } + + void LoginBadRequest(IDictionary data) + { + _errors = data.SelectMany(x => x.Value).Select(x => $"• {x}"); + } + + void LoginUnauthorized() + { + _errors = [ "Incorrect account data" ]; + } + } + + private async Task Register() + { + if (_registerModel.Password != _passwordConfirmation) + { + _errors = [ "Password fields don't match" ]; + return; + } + + await AccountsWebAPIService.Register(_registerModel, RegisterSuccess, RegisterBadRequest); + + void RegisterSuccess(RegisterResponse data) + { + _authType = AuthType.SignIn; + } + + void RegisterBadRequest(IDictionary data) + { + _errors = data.SelectMany(x => x.Value).Select(x => $"• {x}"); + } + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Pages/AuthPage.razor.css b/WatchIt.Website/WatchIt.Website/Pages/AuthPage.razor.css new file mode 100644 index 0000000..35fd5d3 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Pages/AuthPage.razor.css @@ -0,0 +1,14 @@ +/* TAGS */ + +html { + height: 100%; +} + + + +/* CLASSES */ + +.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/HomePage.razor similarity index 100% rename from WatchIt.Website/WatchIt.Website/Pages/Home.razor rename to WatchIt.Website/WatchIt.Website/Pages/HomePage.razor diff --git a/WatchIt.Website/WatchIt.Website/Pages/HomePage.razor.cs b/WatchIt.Website/WatchIt.Website/Pages/HomePage.razor.cs new file mode 100644 index 0000000..3383e8e --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Pages/HomePage.razor.cs @@ -0,0 +1,6 @@ +namespace WatchIt.Website.Pages; + +public partial class HomePage +{ + +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Pages/MovieDataPage.razor b/WatchIt.Website/WatchIt.Website/Pages/MovieDataPage.razor index 51d9167..5707ab5 100644 --- a/WatchIt.Website/WatchIt.Website/Pages/MovieDataPage.razor +++ b/WatchIt.Website/WatchIt.Website/Pages/MovieDataPage.razor @@ -1,6 +1 @@ -@page "/movies/{id:long}" - - -@code { - -} \ No newline at end of file +@page "/movies/{id:long}" \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Pages/MovieEditPage.razor b/WatchIt.Website/WatchIt.Website/Pages/MovieEditPage.razor index 1c085c2..991f676 100644 --- a/WatchIt.Website/WatchIt.Website/Pages/MovieEditPage.razor +++ b/WatchIt.Website/WatchIt.Website/Pages/MovieEditPage.razor @@ -13,7 +13,7 @@

@(Id is null ? "Create new movie" : $"Edit movie \"{_movieInfo.Title}\"")

- + } else { diff --git a/WatchIt.Website/WatchIt.Website/wwwroot/app.css b/WatchIt.Website/WatchIt.Website/wwwroot/app.css index dbb43ae..122f5a6 100644 --- a/WatchIt.Website/WatchIt.Website/wwwroot/app.css +++ b/WatchIt.Website/WatchIt.Website/wwwroot/app.css @@ -80,4 +80,8 @@ body, html { .dropdown-menu-left { right: auto; left: 0; +} + +.btn-stretch-x { + width: 100%; } \ No newline at end of file