diff --git a/Project/adminBlazor/adminBlazor.Api/images/.png b/Project/adminBlazor/adminBlazor.Api/images/.png new file mode 100644 index 0000000..b05a5f7 Binary files /dev/null and b/Project/adminBlazor/adminBlazor.Api/images/.png differ diff --git a/Project/adminBlazor/adminBlazor.Api/images/Alice.png b/Project/adminBlazor/adminBlazor.Api/images/Alice.png new file mode 100644 index 0000000..7595e41 Binary files /dev/null and b/Project/adminBlazor/adminBlazor.Api/images/Alice.png differ diff --git a/Project/adminBlazor/adminBlazor.Api/images/Bob.png b/Project/adminBlazor/adminBlazor.Api/images/Bob.png new file mode 100644 index 0000000..7595e41 Binary files /dev/null and b/Project/adminBlazor/adminBlazor.Api/images/Bob.png differ diff --git a/Project/adminBlazor/adminBlazor.Api/images/John.png b/Project/adminBlazor/adminBlazor.Api/images/John.png new file mode 100644 index 0000000..7595e41 Binary files /dev/null and b/Project/adminBlazor/adminBlazor.Api/images/John.png differ diff --git a/Project/adminBlazor/adminBlazor.Api/images/apple.png b/Project/adminBlazor/adminBlazor.Api/images/apple.png new file mode 100644 index 0000000..c864f6a Binary files /dev/null and b/Project/adminBlazor/adminBlazor.Api/images/apple.png differ diff --git a/Project/adminBlazor/adminBlazor.Api/images/banane.png b/Project/adminBlazor/adminBlazor.Api/images/banane.png new file mode 100644 index 0000000..7595e41 Binary files /dev/null and b/Project/adminBlazor/adminBlazor.Api/images/banane.png differ diff --git a/Project/adminBlazor/adminBlazor.Api/images/default.jpeg b/Project/adminBlazor/adminBlazor.Api/images/default.jpeg new file mode 100644 index 0000000..43faded Binary files /dev/null and b/Project/adminBlazor/adminBlazor.Api/images/default.jpeg differ diff --git a/Project/adminBlazor/adminBlazor.Api/images/default1.png b/Project/adminBlazor/adminBlazor.Api/images/default1.png new file mode 100644 index 0000000..c864f6a Binary files /dev/null and b/Project/adminBlazor/adminBlazor.Api/images/default1.png differ diff --git a/Project/adminBlazor/adminBlazor/Models/AppUser.cs b/Project/adminBlazor/adminBlazor/Models/AppUser.cs new file mode 100644 index 0000000..7121a6a --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Models/AppUser.cs @@ -0,0 +1,9 @@ +namespace adminBlazor.Models +{ + public class AppUser + { + public string Password { get; set; } + public List Roles { get; set; } + public string UserName { get; set; } + } +} diff --git a/Project/adminBlazor/adminBlazor/Models/CurrentUser..cs b/Project/adminBlazor/adminBlazor/Models/CurrentUser..cs new file mode 100644 index 0000000..4eab865 --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Models/CurrentUser..cs @@ -0,0 +1,9 @@ +namespace adminBlazor.Models +{ + public class CurrentUser + { + public Dictionary Claims { get; set; } + public bool IsAuthenticated { get; set; } + public string UserName { get; set; } + } +} diff --git a/Project/adminBlazor/adminBlazor/Models/LoginRequest.cs b/Project/adminBlazor/adminBlazor/Models/LoginRequest.cs new file mode 100644 index 0000000..0d4af4b --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Models/LoginRequest.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; + +namespace adminBlazor.Models +{ + public class LoginRequest + { + [Required] + public string Password { get; set; } + + [Required] + public string UserName { get; set; } + } +} diff --git a/Project/adminBlazor/adminBlazor/Models/RegisterRequest.cs b/Project/adminBlazor/adminBlazor/Models/RegisterRequest.cs new file mode 100644 index 0000000..523ecad --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Models/RegisterRequest.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; + +namespace adminBlazor.Models +{ + public class RegisterRequest + { + [Required] + public string Password { get; set; } + + [Required] + [Compare(nameof(Password), ErrorMessage = "Passwords do not match!")] + public string PasswordConfirm { get; set; } + + [Required] + public string UserName { get; set; } + } +} diff --git a/Project/adminBlazor/adminBlazor/Pages/Authentication/Login.razor b/Project/adminBlazor/adminBlazor/Pages/Authentication/Login.razor new file mode 100644 index 0000000..9cb242b --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Pages/Authentication/Login.razor @@ -0,0 +1,27 @@ +@page "/login" +@layout AuthLayout + +

+ Login +

+ + + diff --git a/Project/adminBlazor/adminBlazor/Pages/Authentication/Login.razor.cs b/Project/adminBlazor/adminBlazor/Pages/Authentication/Login.razor.cs new file mode 100644 index 0000000..6b63d96 --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Pages/Authentication/Login.razor.cs @@ -0,0 +1,32 @@ +using adminBlazor.Models; +using adminBlazor.Services; +using Microsoft.AspNetCore.Components; + +namespace adminBlazor.Pages.Authentication +{ + public partial class Login + { + [Inject] + public CustomStateProvider AuthStateProvider { get; set; } + + [Inject] + public NavigationManager NavigationManager { get; set; } + + private string error { get; set; } + private LoginRequest loginRequest { get; set; } = new LoginRequest(); + + private async Task OnSubmit() + { + error = null; + try + { + await AuthStateProvider.Login(loginRequest); + NavigationManager.NavigateTo(""); + } + catch (Exception ex) + { + error = ex.Message; + } + } + } +} diff --git a/Project/adminBlazor/adminBlazor/Pages/Authentication/Register.razor b/Project/adminBlazor/adminBlazor/Pages/Authentication/Register.razor new file mode 100644 index 0000000..a8e7602 --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Pages/Authentication/Register.razor @@ -0,0 +1,29 @@ +@page "/register" +@layout AuthLayout + +

+ Register +

+ + \ No newline at end of file diff --git a/Project/adminBlazor/adminBlazor/Pages/Authentication/Register.razor.cs b/Project/adminBlazor/adminBlazor/Pages/Authentication/Register.razor.cs new file mode 100644 index 0000000..f6b3178 --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Pages/Authentication/Register.razor.cs @@ -0,0 +1,32 @@ +using adminBlazor.Models; +using adminBlazor.Services; +using Microsoft.AspNetCore.Components; + +namespace adminBlazor.Pages.Authentication +{ + public partial class Register + { + [Inject] + public CustomStateProvider AuthStateProvider { get; set; } + + [Inject] + public NavigationManager NavigationManager { get; set; } + + private string error { get; set; } + private RegisterRequest registerRequest { get; set; } = new RegisterRequest(); + + private async Task OnSubmit() + { + error = null; + try + { + await AuthStateProvider.Register(registerRequest); + NavigationManager.NavigateTo(""); + } + catch (Exception ex) + { + error = ex.Message; + } + } + } +} diff --git a/Project/adminBlazor/adminBlazor/Program.cs b/Project/adminBlazor/adminBlazor/Program.cs index 350b345..f59fe3a 100644 --- a/Project/adminBlazor/adminBlazor/Program.cs +++ b/Project/adminBlazor/adminBlazor/Program.cs @@ -24,7 +24,7 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddScoped(); -//builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/Project/adminBlazor/adminBlazor/Services/AuthService.cs b/Project/adminBlazor/adminBlazor/Services/AuthService.cs new file mode 100644 index 0000000..96ece5b --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Services/AuthService.cs @@ -0,0 +1,53 @@ +using adminBlazor.Models; +using System.Security.Claims; + +namespace adminBlazor.Services +{ + public class AuthService : IAuthService + { + private static readonly List CurrentUser; + + static AuthService() + { + CurrentUser = new List + { + new AppUser { UserName = "Admin", Password = "123456", Roles = new List { "admin" } } + }; + } + + public CurrentUser GetUser(string userName) + { + var user = CurrentUser.FirstOrDefault(w => w.UserName == userName); + + if (user == null) + { + throw new Exception("User name or password invalid !"); + } + + var claims = new List(); + claims.AddRange(user.Roles.Select(s => new Claim(ClaimTypes.Role, s))); + + return new CurrentUser + { + IsAuthenticated = true, + UserName = user.UserName, + Claims = claims.ToDictionary(c => c.Type, c => c.Value) + }; + } + + public void Login(LoginRequest loginRequest) + { + var user = CurrentUser.FirstOrDefault(w => w.UserName == loginRequest.UserName && w.Password == loginRequest.Password); + + if (user == null) + { + throw new Exception("User name or password invalid !"); + } + } + + public void Register(RegisterRequest registerRequest) + { + CurrentUser.Add(new AppUser { UserName = registerRequest.UserName, Password = registerRequest.Password, Roles = new List { "guest" } }); + } + } +} diff --git a/Project/adminBlazor/adminBlazor/Services/CustomStateProvider.cs b/Project/adminBlazor/adminBlazor/Services/CustomStateProvider.cs new file mode 100644 index 0000000..ab9d69e --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Services/CustomStateProvider.cs @@ -0,0 +1,75 @@ +using adminBlazor.Models; +using Microsoft.AspNetCore.Components.Authorization; +using System.Security.Claims; + +namespace adminBlazor.Services +{ + public class CustomStateProvider : AuthenticationStateProvider + { + private readonly IAuthService _authService; + private CurrentUser _currentUser; + + public CustomStateProvider(IAuthService authService) + { + this._authService = authService; + } + + public override async Task GetAuthenticationStateAsync() + { + var identity = new ClaimsIdentity(); + try + { + var userInfo = GetCurrentUser(); + if (userInfo.IsAuthenticated) + { + var claims = new[] { new Claim(ClaimTypes.Name, _currentUser.UserName) }.Concat(_currentUser.Claims.Select(c => new Claim(c.Key, c.Value))); + identity = new ClaimsIdentity(claims, "Server authentication"); + } + } + catch (HttpRequestException ex) + { + Console.WriteLine("Request failed:" + ex); + } + + return new AuthenticationState(new ClaimsPrincipal(identity)); + } + + public async Task Login(LoginRequest loginParameters) + { + _authService.Login(loginParameters); + + // No error - Login the user + var user = _authService.GetUser(loginParameters.UserName); + _currentUser = user; + + NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); + } + + public async Task Logout() + { + _currentUser = null; + NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); + } + + public async Task Register(RegisterRequest registerParameters) + { + _authService.Register(registerParameters); + + // No error - Login the user + var user = _authService.GetUser(registerParameters.UserName); + _currentUser = user; + + NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); + } + + private CurrentUser GetCurrentUser() + { + if (_currentUser != null && _currentUser.IsAuthenticated) + { + return _currentUser; + } + + return new CurrentUser(); + } + } +} diff --git a/Project/adminBlazor/adminBlazor/Services/DataLocalService.cs b/Project/adminBlazor/adminBlazor/Services/DataLocalService.cs new file mode 100644 index 0000000..77fe608 --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Services/DataLocalService.cs @@ -0,0 +1,137 @@ +using adminBlazor.Factories; +using adminBlazor.Models; +using Blazored.LocalStorage; +using Blazorise.Extensions; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Hosting; + +namespace adminBlazor.Services +{ + public class DataLocalService : IDataService + { + private readonly HttpClient _http; + private readonly ILocalStorageService _localStorage; + private readonly NavigationManager _navigationManager; + private readonly IWebHostEnvironment _webHostEnvironment; + public DataLocalService( + ILocalStorageService localStorage, + HttpClient http, + IWebHostEnvironment webHostEnvironment, + NavigationManager navigationManager) + { + _localStorage = localStorage; + _webHostEnvironment = webHostEnvironment; + _navigationManager = navigationManager; + _http = http; + + } + + public async Task Add(UserModel model) + { + var currentData = await _localStorage.GetItemAsync>("data"); + + // Simulate the Id + model.Id = currentData.Max(s => s.Id) + 1; + + // Add the item to the current data + currentData.Add(UserFactory.Create(model)); + + // Save the image + + + // Save the data + await _localStorage.SetItemAsync("data", currentData); + + + } + + public async Task Count() + { + // Load data from the local storage + var currentData = await _localStorage.GetItemAsync("data"); + + // Check if data exist in the local storage + if (currentData == null) + { + // this code add in the local storage the fake data + var originalData = await _http.GetFromJsonAsync($"{_navigationManager.BaseUri}fake-data.json"); + await _localStorage.SetItemAsync("data", originalData); + } + + return (await _localStorage.GetItemAsync("data")).Length; + } + + public async Task GetById(int id) + { + + var currentData = await _localStorage.GetItemAsync>("data"); + + var user = currentData.FirstOrDefault(w => w.Id == id); + + if (user == null) + { + throw new Exception($"Unable to found the item with ID: {id}"); + } + + return user; + } + + public async Task> List(int currentPage, int pageSize) + { + // Load data from the local storage + var currentData = await _localStorage.GetItemAsync("data"); + + // Check if data exist in the local storage + if (currentData == null) + { + // this code add in the local storage the fake data + var originalData = await _http.GetFromJsonAsync($"{_navigationManager.BaseUri}user.json"); + await _localStorage.SetItemAsync("data", originalData); + } + + return (await _localStorage.GetItemAsync("data")).Skip((currentPage - 1) * pageSize).Take(pageSize).ToList(); + } + + public async Task Update(int id, UserModel model) + { + // Get the current data + var currentData = await _localStorage.GetItemAsync>("data"); + + var user = currentData.FirstOrDefault(w => w.Id == id); + + if (user == null) + { + throw new Exception($"Unable to found the item with ID: {id}"); + } + + // Save the image + // + + UserFactory.Update(user, model); + + // Modify the content of the item + + + // Save the data + await _localStorage.SetItemAsync("data", currentData); + } + + public async Task Delete(int id) + { + // Get the current data + var currentData = await _localStorage.GetItemAsync>("data"); + + // Get the item int the list + var item = currentData.FirstOrDefault(w => w.Id == id); + + // Delete item in + currentData.Remove(item); + + // Delete the image + + + // Save the data + await _localStorage.SetItemAsync("data", currentData); + } + } +} diff --git a/Project/adminBlazor/adminBlazor/Services/IAuthService.cs b/Project/adminBlazor/adminBlazor/Services/IAuthService.cs new file mode 100644 index 0000000..84dc7ca --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Services/IAuthService.cs @@ -0,0 +1,13 @@ +using adminBlazor.Models; + +namespace adminBlazor.Services +{ + public interface IAuthService + { + CurrentUser GetUser(string userName); + + void Login(LoginRequest loginRequest); + + void Register(RegisterRequest registerRequest); + } +} diff --git a/Project/adminBlazor/adminBlazor/Shared/AuthLayout.razor b/Project/adminBlazor/adminBlazor/Shared/AuthLayout.razor new file mode 100644 index 0000000..ae7bc2a --- /dev/null +++ b/Project/adminBlazor/adminBlazor/Shared/AuthLayout.razor @@ -0,0 +1,6 @@ +@inherits LayoutComponentBase +
+
+ @Body +
+
\ No newline at end of file