From 9f395ac634215a406268d99af9feee472b603047 Mon Sep 17 00:00:00 2001 From: Maciej Maciejewski Date: Wed, 23 Oct 2024 23:16:01 +0200 Subject: [PATCH 1/4] =?UTF-8?q?dodanie=20logowania=20u=C5=BCytkownika=20-?= =?UTF-8?q?=20b=C5=82=C4=85d=20tworzenia=20tokenu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Authentication/AuthenticationSettings.cs | 9 ++ Controllers/ProductController.cs | 5 + Controllers/UserController.cs | 50 +++++++ Entities/User.cs | 12 ++ Exceptions/NoResultsException.cs | 11 ++ Exceptions/PermissionException.cs | 11 ++ Exceptions/WrongUserOrPasswordException.cs | 11 ++ FirmTracker-Server.csproj | 20 ++- Helpers/RolesHelper.cs | 13 ++ Logger.cs | 75 +++++++++++ Mappings/LicenseMappingProfile.cs | 24 ++++ Middleware/ErrorHandling.cs | 43 ++++++ Models/CreateUserDto.cs | 11 ++ Models/LoginDtocs.cs | 9 ++ Models/UserDto.cs | 22 ++++ Program.cs | 65 +++++++++- Services/UserService.cs | 144 +++++++++++++++++++++ TestClass.cs | 12 ++ appsettings.json | 52 ++++---- nHIbernate/LogsMapping.cs | 30 +++++ nHIbernate/SessionFactory.cs | 5 +- nHIbernate/UserMapping.cs | 16 +++ 22 files changed, 620 insertions(+), 30 deletions(-) create mode 100644 Authentication/AuthenticationSettings.cs create mode 100644 Controllers/UserController.cs create mode 100644 Entities/User.cs create mode 100644 Exceptions/NoResultsException.cs create mode 100644 Exceptions/PermissionException.cs create mode 100644 Exceptions/WrongUserOrPasswordException.cs create mode 100644 Helpers/RolesHelper.cs create mode 100644 Logger.cs create mode 100644 Mappings/LicenseMappingProfile.cs create mode 100644 Middleware/ErrorHandling.cs create mode 100644 Models/CreateUserDto.cs create mode 100644 Models/LoginDtocs.cs create mode 100644 Models/UserDto.cs create mode 100644 Services/UserService.cs create mode 100644 nHIbernate/LogsMapping.cs create mode 100644 nHIbernate/UserMapping.cs diff --git a/Authentication/AuthenticationSettings.cs b/Authentication/AuthenticationSettings.cs new file mode 100644 index 0000000..cd15356 --- /dev/null +++ b/Authentication/AuthenticationSettings.cs @@ -0,0 +1,9 @@ +namespace FirmTracker_Server.Authentication +{ + public class AuthenticationSettings + { + public string JwtSecKey { get; set; } + public int JwtExpireDays { get; set; } + public string JwtIssuer { get; set; } + } +} diff --git a/Controllers/ProductController.cs b/Controllers/ProductController.cs index d662d96..ec6b5d3 100644 --- a/Controllers/ProductController.cs +++ b/Controllers/ProductController.cs @@ -16,6 +16,8 @@ */ using FirmTracker_Server.nHibernate.Products; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization.Infrastructure; using Microsoft.AspNetCore.Mvc; using System; @@ -23,6 +25,7 @@ namespace FirmTracker_Server.Controllers { [Route("api/[controller]")] [ApiController] + [Authorize] public class ProductsController : ControllerBase { private readonly ProductCRUD _productCrud; @@ -39,6 +42,7 @@ namespace FirmTracker_Server.Controllers [HttpPost] [ProducesResponseType(200)] // Created [ProducesResponseType(400)] // Bad Request + [Authorize(Roles = Roles.User)] public IActionResult CreateProduct([FromBody] Product product) { try @@ -162,6 +166,7 @@ namespace FirmTracker_Server.Controllers [HttpGet] [ProducesResponseType(200)] // Created [ProducesResponseType(400)] // Bad Request + [Authorize(Roles =Roles.User)] public IActionResult GetAllProducts() { var products = _productCrud.GetAllProducts(); diff --git a/Controllers/UserController.cs b/Controllers/UserController.cs new file mode 100644 index 0000000..4175696 --- /dev/null +++ b/Controllers/UserController.cs @@ -0,0 +1,50 @@ +using FirmTracker_Server.Models; +using FirmTracker_Server.Services; +using FirmTracker_Server; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using FirmTracker_Server.Entities; + +namespace FirmTracker_Server.Controllers +{ + [Route("api/user")] + [ApiController] + [Authorize] + public class UserController : ControllerBase + { + private readonly IUserService UserService; + + public UserController(IUserService userService) + { + UserService = userService; + } + + [HttpPost("create")] + [Authorize(Roles = Roles.Admin)] + public ActionResult CreateUser([FromBody] CreateUserDto dto) + { + if (!ModelState.IsValid) + { + return BadRequest("Nieprawidłowa wartość pola. /n" + ModelState); + } + var id = UserService.AddUser(dto); + return Created($"/api/user/{id}", "User dodany poprawnie"); + } + + [HttpPost("login")] + [AllowAnonymous] + public ActionResult Login([FromBody] LoginDto dto) + { + var token = UserService.CreateTokenJwt(dto); + return Ok(token); + } + // New method to get all users + /* [HttpGet("all")] + [AllowAnonymous] + public ActionResult> GetAllUsers() + { + var users = UserService.GetAllUsers(); + return Ok(users); + }*/ + } +} diff --git a/Entities/User.cs b/Entities/User.cs new file mode 100644 index 0000000..1282962 --- /dev/null +++ b/Entities/User.cs @@ -0,0 +1,12 @@ +namespace FirmTracker_Server.Entities +{ + public class User + { + public virtual int Id { get; set; } + public virtual string Login { get; set; } + public virtual string Email { get; set; } + public virtual string Role { get; set; } = "User"; + public virtual string PassHash { get; set; } + public virtual bool NewEncryption { get; set; } + } +} diff --git a/Exceptions/NoResultsException.cs b/Exceptions/NoResultsException.cs new file mode 100644 index 0000000..4526540 --- /dev/null +++ b/Exceptions/NoResultsException.cs @@ -0,0 +1,11 @@ +namespace FirmTracker_Server.Exceptions +{ + public class NoResultsException : Exception + { + public NoResultsException() : base("Brak wyników") { } + + public NoResultsException(string message) : base(message) { } + + public NoResultsException(string message, Exception innerException) : base(message, innerException) { } + } +} \ No newline at end of file diff --git a/Exceptions/PermissionException.cs b/Exceptions/PermissionException.cs new file mode 100644 index 0000000..ad6b208 --- /dev/null +++ b/Exceptions/PermissionException.cs @@ -0,0 +1,11 @@ +namespace FirmTracker_Server.Exceptions +{ + public class PermissionException : Exception + { + public PermissionException() : base("Brak uprawnień") { } + + public PermissionException(string message) : base(message) { } + + public PermissionException(string message, Exception innerException) : base(message, innerException) { } + } +} \ No newline at end of file diff --git a/Exceptions/WrongUserOrPasswordException.cs b/Exceptions/WrongUserOrPasswordException.cs new file mode 100644 index 0000000..a926c0f --- /dev/null +++ b/Exceptions/WrongUserOrPasswordException.cs @@ -0,0 +1,11 @@ +namespace FirmTracker_Server.Exceptions +{ + public class WrongUserOrPasswordException : Exception + { + public WrongUserOrPasswordException() : base("Nieprawidłowy użytkownik lub hasło.") { } + + public WrongUserOrPasswordException(string message) : base(message) { } + + public WrongUserOrPasswordException(string message, Exception innerException) : base(message, innerException) { } + } +} diff --git a/FirmTracker-Server.csproj b/FirmTracker-Server.csproj index c4a467b..91768c3 100644 --- a/FirmTracker-Server.csproj +++ b/FirmTracker-Server.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0-windows enable enable FirmTracker_Server @@ -17,13 +17,27 @@ - + + + + + + - + + + + + + + + + ..\..\..\Desktop\szyfrowanie.dll + diff --git a/Helpers/RolesHelper.cs b/Helpers/RolesHelper.cs new file mode 100644 index 0000000..868a17c --- /dev/null +++ b/Helpers/RolesHelper.cs @@ -0,0 +1,13 @@ +namespace FirmTracker_Server +{ + public static class RolesHelper + { + public static IEnumerable GetRoles() => new List { Roles.Admin, Roles.User }; + } + + public static class Roles + { + public const string Admin = "Admin"; + public const string User = "User"; + } +} \ No newline at end of file diff --git a/Logger.cs b/Logger.cs new file mode 100644 index 0000000..2a40f6c --- /dev/null +++ b/Logger.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; +using NLog; +using NLog.Config; +using NLog.Targets; + + +namespace IntegrationWithCzech +{ + public static class Logger + { + private static NLog.Logger log; + + public static void ConfigLog() + { + var config = new LoggingConfiguration(); + + string appDirectory = Directory.GetCurrentDirectory(); + string configFilePath = Path.Combine(appDirectory, "appsettings.json"); + var config1 = new ConfigurationBuilder() + .AddJsonFile(configFilePath) + .Build(); + var connectionstringsection = config1.GetSection("AppSettings:ConnectionString"); + + string connectionString = connectionstringsection.Value; + + // Czech Database Target + var LogDbTarget = new DatabaseTarget("logDBTarget") + { + ConnectionString = connectionString, + CommandText = "INSERT INTO CDN.CzechLogTable(Date, Level, Message, Exception) VALUES(@date, @level, @message, @exception)" + }; + LogDbTarget.Parameters.Add(new DatabaseParameterInfo("@date", "${longdate}")); + LogDbTarget.Parameters.Add(new DatabaseParameterInfo("@level", "${level}")); + LogDbTarget.Parameters.Add(new DatabaseParameterInfo("@message", "${message}")); + LogDbTarget.Parameters.Add(new DatabaseParameterInfo("@exception", "${exception}")); + + + var logconsole = new ConsoleTarget("logconsole") + { + Layout = "${longdate} ${message} ${exception}" + }; + + + + // Adding Rules for Poland Logging + config.AddRuleForOneLevel(NLog.LogLevel.Error, LogDbTarget, "PolandLogger"); + config.AddRuleForAllLevels(logconsole, "PolandLogger"); + + LogManager.Configuration = config; + log = LogManager.GetLogger("CzechLogger"); + + } + + public static void LogInfo(string message) + { + log?.Info(message); + } + + + + public static void Write2CzechLogError(string message, Exception ex = null) + { + if (ex is null) + { + log?.Error(message); + } + else + { + log?.Error(ex, message); + } + } + + } +} diff --git a/Mappings/LicenseMappingProfile.cs b/Mappings/LicenseMappingProfile.cs new file mode 100644 index 0000000..7dea6e0 --- /dev/null +++ b/Mappings/LicenseMappingProfile.cs @@ -0,0 +1,24 @@ +using AutoMapper; +using FirmTracker_Server.Entities; +using FirmTracker_Server.Models; +using NHibernate.Type; +using NuGet.Packaging.Licenses; +using System.ComponentModel; + +namespace FirmTracker_Server.Mappings +{ + public class LicenseMappingProfile : Profile + { + public LicenseMappingProfile() + { + // CreateMap(); + // CreateMap(); + // CreateMap(); + // CreateMap(); + // CreateMap(); + CreateMap(); + CreateMap(); + CreateMap().ForSourceMember(x => x.Password, y => y.DoNotValidate()); + } + } +} diff --git a/Middleware/ErrorHandling.cs b/Middleware/ErrorHandling.cs new file mode 100644 index 0000000..c023aba --- /dev/null +++ b/Middleware/ErrorHandling.cs @@ -0,0 +1,43 @@ +using FirmTracker_Server.Exceptions; + +namespace FirmTracker_Server.Middleware +{ + public class ErrorHandling : IMiddleware + { + private readonly ILogger Logger; + + public ErrorHandling(ILogger logger) + { + Logger = logger; + } + + public async Task InvokeAsync(HttpContext context, RequestDelegate next) + { + try + { + await next.Invoke(context); + } + catch (WrongUserOrPasswordException ex) + { + context.Response.StatusCode = 400; + await context.Response.WriteAsync(ex.Message); + } + catch (PermissionException ex) + { + context.Response.StatusCode = 403; + await context.Response.WriteAsync(ex.Message); + } + catch (NoResultsException ex) + { + context.Response.StatusCode = 404; + await context.Response.WriteAsync(ex.Message); + } + catch (Exception ex) + { + Logger.LogError(ex, "Wystąpił nieoczekiwany błąd."); + context.Response.StatusCode = 500; + await context.Response.WriteAsJsonAsync("Wystąpił nieoczekiwany błąd."); + } + } + } +} diff --git a/Models/CreateUserDto.cs b/Models/CreateUserDto.cs new file mode 100644 index 0000000..b282e21 --- /dev/null +++ b/Models/CreateUserDto.cs @@ -0,0 +1,11 @@ +namespace FirmTracker_Server.Models +{ + public class CreateUserDto + { + public string Login { get; set; } + public string Password { get; set; } + public string Email { get; set; } + public string Role { get; set; } + public bool NewEncryption { get; set; } = true; + } +} diff --git a/Models/LoginDtocs.cs b/Models/LoginDtocs.cs new file mode 100644 index 0000000..65628d7 --- /dev/null +++ b/Models/LoginDtocs.cs @@ -0,0 +1,9 @@ +namespace FirmTracker_Server.Models +{ + public class LoginDto + { + public string Email { get; set; } + public string Password { get; set; } + + } +} diff --git a/Models/UserDto.cs b/Models/UserDto.cs new file mode 100644 index 0000000..da941b6 --- /dev/null +++ b/Models/UserDto.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace FirmTracker_Server.Models +{ + public class UserDto + { + [Required] + [MaxLength(16)] + public string Login { get; set; } + + [Required] + [EmailAddress] + public string Email { get; set; } + + [Required] + [MinLength(8, ErrorMessage = "Password must be at least 8 characters long.")] + [MaxLength(100, ErrorMessage = "Password cannot be longer than 100 characters.")] + [RegularExpression(@"^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&#])[A-Za-z\d@$!%*?&#]{8,}$", ErrorMessage = "Password must contain at least one uppercase letter, one lowercase letter, one digit, and one special character.")] + public string Password { get; set; } + + } +} \ No newline at end of file diff --git a/Program.cs b/Program.cs index d5d0597..2c10c9c 100644 --- a/Program.cs +++ b/Program.cs @@ -24,13 +24,27 @@ using FirmTracker_Server.nHibernate.Products; using FirmTracker_Server.nHibernate; using FirmTracker_Server.Utilities.Converters; using FirmTracker_Server.Utilities.Swagger; +using FluentValidation; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.AspNetCore.Identity; +using Microsoft.IdentityModel.Tokens; +using AutoMapper; +using Microsoft.AspNetCore.Authentication; +using System.Text; +using FirmTracker_Server.Entities; +using FirmTracker_Server.Middleware; +using FirmTracker_Server.Services; +using System.Reflection; +using FirmTracker_Server.Mappings; + namespace FirmTracker_Server { - public class Program + internal static class Program { - public static void Main(string[] args) + public static async Task Main(string[] args) { var builder = WebApplication.CreateBuilder(args); string appDirectory = Directory.GetCurrentDirectory(); @@ -55,6 +69,7 @@ namespace FirmTracker_Server TestClass test = new TestClass(); test.AddTestProduct(); + builder.Services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", @@ -62,19 +77,24 @@ namespace FirmTracker_Server .AllowAnyHeader() .AllowAnyMethod()); }); + builder.Services.ConfigureAutoMapper(); + builder.Services.ConfigureServiceInjection(); builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new DateTimeConverter()); }); ; - + builder.ConfigureAuthentication(); + builder.Services.AddAuthorization(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SchemaFilter(); }); + + var app = builder.Build(); var configSwagger = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) @@ -107,6 +127,7 @@ namespace FirmTracker_Server app.UseCors("AllowSpecificOrigin"); + app.UseAuthentication(); app.UseAuthorization(); @@ -117,5 +138,43 @@ namespace FirmTracker_Server app.Run(); } + private static void ConfigureAuthentication(this WebApplicationBuilder builder) + { + var authenticationSettings = new Authentication.AuthenticationSettings(); + builder.Configuration.GetSection("TokenConfig").Bind(authenticationSettings); + builder.Services.AddAuthentication(option => { + option.DefaultAuthenticateScheme = "Bearer"; + option.DefaultScheme = "Bearer"; + option.DefaultChallengeScheme = "Bearer"; + }).AddJwtBearer(options => { + options.RequireHttpsMetadata = false; + options.SaveToken = true; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidIssuer = authenticationSettings.JwtIssuer, + ValidAudience = authenticationSettings.JwtIssuer, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authenticationSettings.JwtSecKey)), + }; + }); + builder.Services.AddSingleton(authenticationSettings); + } + private static void ConfigureAutoMapper(this IServiceCollection services) + { + var mapperConfig = new MapperConfiguration(mc => { + mc.AddProfile(); + // mc.AddProfile(); + }); + var mapper = mapperConfig.CreateMapper(); + services.AddSingleton(mapper); + services.AddAutoMapper(Assembly.GetExecutingAssembly()); + } + private static void ConfigureServiceInjection(this IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + services.AddScoped, PasswordHasher>(); + services.AddMvc(); + } + } } diff --git a/Services/UserService.cs b/Services/UserService.cs new file mode 100644 index 0000000..4b5cc53 --- /dev/null +++ b/Services/UserService.cs @@ -0,0 +1,144 @@ +using AutoMapper; +using FirmTracker_Server.Authentication; +using FirmTracker_Server.Entities; +using FirmTracker_Server.Exceptions; +using FirmTracker_Server.Models; +using FirmTracker_Server.Authentication; +using FirmTracker_Server.Exceptions; +using Microsoft.AspNetCore.Identity; +using Microsoft.IdentityModel.Tokens; +using System.Globalization; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using szyfrowanie; +using FirmTracker_Server.nHibernate; +using NHibernate; +using NHibernate.Criterion; + +namespace FirmTracker_Server.Services +{ + public interface IUserService + { + UserDto GetById(int id); + int AddUser(CreateUserDto dto); + string CreateTokenJwt(LoginDto dto); + + } + + public class UserService : IUserService + { + // private readonly GeneralDbContext DbContext; + private readonly IMapper Mapper; + private readonly IPasswordHasher PasswordHasher; + private readonly AuthenticationSettings AuthenticationSettings; + private readonly SimplerAES SimplerAES; + //private readonly SessionFactory sessionFactory; + + public UserService( IMapper mapper, IPasswordHasher passwordHasher, AuthenticationSettings authenticationSettings) + { + // DbContext = dbContext; + Mapper = mapper; + PasswordHasher = passwordHasher; + AuthenticationSettings = authenticationSettings; + SimplerAES = new SimplerAES(); + //SessionFactory = sessionFactory; + } + + public UserDto GetById(int id) + { + using (var session = SessionFactory.OpenSession()) + { + var user = session.Get(id); + return user == null ? null : Mapper.Map(user); + } + } + + public int AddUser(CreateUserDto dto) + { + var user = Mapper.Map(dto); + + // Encrypt or hash the password based on NewEncryption flag + user.PassHash = dto.NewEncryption ? SimplerAES.Encrypt(dto.Password) : PasswordHasher.HashPassword(user, dto.Password); + user.Role = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(dto.Role.ToLower()); + + using (var session = SessionFactory.OpenSession()) + using (var transaction = session.BeginTransaction()) + { + try + { + session.Save(user); + transaction.Commit(); + return user.Id; + } + catch + { + transaction.Rollback(); + throw; + } + } + } + + public string CreateTokenJwt(LoginDto dto) + { + User user = null; + + using (var session = SessionFactory.OpenSession()) + { + if (!string.IsNullOrEmpty(dto.Email)) + { + user = session.Query().FirstOrDefault(x => x.Email == dto.Email); + } + else + { + throw new WrongUserOrPasswordException("Nieprawidłowy login lub hasło."); + } + + if (user == null) + { + throw new WrongUserOrPasswordException("Nieprawidłowy login lub hasło."); + } + + // Password verification logic + if (user.NewEncryption) + { + try + { + Console.WriteLine(SimplerAES.Decrypt(user.PassHash)+" "+SimplerAES.Decrypt(dto.Password)); + var ready = SimplerAES.Decrypt(user.PassHash) == SimplerAES.Decrypt(dto.Password); + if (!ready) + { + throw new WrongUserOrPasswordException("Nieprawidłowy login lub hasło."); + } + } + catch (Exception) + { + throw new WrongUserOrPasswordException("Wystąpił błąd podczas logowania"); + } + } + else + { + var ready = PasswordVerificationResult.Failed; + if (SimplerAES.Decrypt(user.PassHash) == SimplerAES.Decrypt(dto.Password)) { ready = PasswordVerificationResult.Success; } //PasswordHasher.VerifyHashedPassword(user, user.PassHash, dto.Password); + if (ready == PasswordVerificationResult.Failed) + { + throw new WrongUserOrPasswordException("Nieprawidłowy login lub hasło."); + } + } + + // Generate JWT token + var claims = new List() { + new(ClaimTypes.NameIdentifier, user.Id.ToString()), + new(ClaimTypes.Role, user.Role) + }; + + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AuthenticationSettings.JwtSecKey)); + var credential = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + var expires = DateTime.Now.AddDays(AuthenticationSettings.JwtExpireDays); + var token = new JwtSecurityToken(AuthenticationSettings.JwtIssuer, AuthenticationSettings.JwtIssuer, claims, expires: expires, signingCredentials: credential); + var finalToken = new JwtSecurityTokenHandler(); + return finalToken.WriteToken(token); + } + } + } +} diff --git a/TestClass.cs b/TestClass.cs index 5e28ecf..f06f43b 100644 --- a/TestClass.cs +++ b/TestClass.cs @@ -21,6 +21,12 @@ using FirmTracker_Server.nHibernate.Products; using FirmTracker_Server.nHibernate.Transactions; using FirmTracker_Server.nHibernate.Expenses; using NHibernate; +using FirmTracker_Server.Entities; +using FirmTracker_Server.Services; +using AutoMapper; +using FirmTracker_Server.Authentication; +using Microsoft.AspNetCore.Identity; +using FirmTracker_Server.Models; namespace FirmTracker_Server { @@ -162,10 +168,16 @@ namespace FirmTracker_Server }; + + + + + try { FirmTracker_Server.nHibernate.Products.ProductCRUD productCrud = new ProductCRUD(); FirmTracker_Server.nHibernate.Transactions.TransactionCRUD transactionCrud = new nHibernate.Transactions.TransactionCRUD(); + ExpenseCRUD expenseCrud = new ExpenseCRUD(); // productCrud.AddProduct(product); productCrud.AddProduct(product2); diff --git a/appsettings.json b/appsettings.json index 61b3a7a..52639ff 100644 --- a/appsettings.json +++ b/appsettings.json @@ -1,29 +1,35 @@ { "AppSettings": { "ConnectionString": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=master;Integrated Security=True;" + }, - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", - "applicationUrl": "http://localhost:5045" - - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", - "applicationUrl": "https://localhost:7039" - - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "swagger" - - } + "TokenConfig": { + "JwtSecKey": "omgi5Rf4tqg351GQwefw", + "JwtExpireDays": 30, + "JwtIssuer": "http://api.graphcom.pl" + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5045" + + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7039" + + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger" + } + } } \ No newline at end of file diff --git a/nHIbernate/LogsMapping.cs b/nHIbernate/LogsMapping.cs new file mode 100644 index 0000000..d154ee9 --- /dev/null +++ b/nHIbernate/LogsMapping.cs @@ -0,0 +1,30 @@ +/* + * This file is part of FirmTracker - Server. + * + * FirmTracker - Server is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FirmTracker - Server is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FirmTracker - Server. If not, see . + */ + +using System.Text.Json.Serialization; + +namespace FirmTracker_Server.nHibernate +{ + public class LogsMapping + { + public virtual int Id { get; set; } + public virtual DateTime Date { get; set; } + public virtual string Level { get; set; } + public virtual string Message { get; set; } + public virtual string Exception { get; set; } + } +} diff --git a/nHIbernate/SessionFactory.cs b/nHIbernate/SessionFactory.cs index f053dc1..6218b36 100644 --- a/nHIbernate/SessionFactory.cs +++ b/nHIbernate/SessionFactory.cs @@ -53,7 +53,10 @@ namespace FirmTracker_Server.nHibernate .AddFromAssemblyOf() .AddFromAssemblyOf() .AddFromAssemblyOf() - .AddFromAssemblyOf(); + .AddFromAssemblyOf() + .AddFromAssemblyOf() + .AddFromAssemblyOf(); + }) .ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true)) //SchemaUpdate . Execute dla only update .BuildSessionFactory(); diff --git a/nHIbernate/UserMapping.cs b/nHIbernate/UserMapping.cs new file mode 100644 index 0000000..44c7e7b --- /dev/null +++ b/nHIbernate/UserMapping.cs @@ -0,0 +1,16 @@ +using FluentNHibernate.Mapping; +using FirmTracker_Server.Entities; + +public class UserMapping : ClassMap +{ + public UserMapping() + { + Table("Users"); // The name of your table in the database + + Id(x => x.Id); // Mapping the Id property + Map(x => x.Email); // Mapping other properties + Map(x => x.PassHash); + Map(x => x.Role); + // Add other mappings as needed + } +} -- 2.20.1 From 034383cadf025f4a3ff31ac85d6d6139d4fd2b1c Mon Sep 17 00:00:00 2001 From: Maciej Maciejewski Date: Thu, 24 Oct 2024 11:28:22 +0200 Subject: [PATCH 2/4] pobieranie tokenu --- Controllers/ProductController.cs | 2 +- appsettings.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Controllers/ProductController.cs b/Controllers/ProductController.cs index ec6b5d3..f1d03ba 100644 --- a/Controllers/ProductController.cs +++ b/Controllers/ProductController.cs @@ -166,7 +166,7 @@ namespace FirmTracker_Server.Controllers [HttpGet] [ProducesResponseType(200)] // Created [ProducesResponseType(400)] // Bad Request - [Authorize(Roles =Roles.User)] + [Authorize(Roles =Roles.Admin)] public IActionResult GetAllProducts() { var products = _productCrud.GetAllProducts(); diff --git a/appsettings.json b/appsettings.json index 52639ff..f9a565b 100644 --- a/appsettings.json +++ b/appsettings.json @@ -4,7 +4,7 @@ }, "TokenConfig": { - "JwtSecKey": "omgi5Rf4tqg351GQwefw", + "JwtSecKey": "omgi5Rf4tqg351GQwefw1234567890123456", "JwtExpireDays": 30, "JwtIssuer": "http://api.graphcom.pl" }, -- 2.20.1 From ccef96c6da37189d36bef5e82a9ec0e77bf6db9e Mon Sep 17 00:00:00 2001 From: Maciej Maciejewski Date: Thu, 24 Oct 2024 20:50:01 +0200 Subject: [PATCH 3/4] =?UTF-8?q?dodanie=20user=C3=B3w=20w=20klasie=20testow?= =?UTF-8?q?ej=20user,=20admin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Controllers/ProductController.cs | 2 +- TestClass.cs | 50 ++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/Controllers/ProductController.cs b/Controllers/ProductController.cs index f1d03ba..e44a3ca 100644 --- a/Controllers/ProductController.cs +++ b/Controllers/ProductController.cs @@ -166,7 +166,7 @@ namespace FirmTracker_Server.Controllers [HttpGet] [ProducesResponseType(200)] // Created [ProducesResponseType(400)] // Bad Request - [Authorize(Roles =Roles.Admin)] + [Authorize(Roles = Roles.Admin + "," + Roles.User)] public IActionResult GetAllProducts() { var products = _productCrud.GetAllProducts(); diff --git a/TestClass.cs b/TestClass.cs index f06f43b..02cd16a 100644 --- a/TestClass.cs +++ b/TestClass.cs @@ -27,6 +27,7 @@ using AutoMapper; using FirmTracker_Server.Authentication; using Microsoft.AspNetCore.Identity; using FirmTracker_Server.Models; +using System.Data.SqlClient; namespace FirmTracker_Server { @@ -168,10 +169,53 @@ namespace FirmTracker_Server }; - + try + { + string appDirectory = Directory.GetCurrentDirectory(); + string configFilePath = Path.Combine(appDirectory, "appsettings.json"); + string connectionString = ""; + if (File.Exists(configFilePath)) + { + var config = new ConfigurationBuilder() + .AddJsonFile(configFilePath) + .Build(); + + var connectionstringsection = config.GetSection("AppSettings:ConnectionString"); + + connectionString = connectionstringsection.Value; + + //SessionFactory.Init(connectionString); + + string queryUser = "insert into Users(Email,PassHash,Role) select '123@wp.pl', 'GOsGemJarMJu8btZKF6Rung27JLZkdO7Wfd4CwLhL1k=','User'"; + string queryAdmin = "insert into Users(Email,PassHash,Role) select '321@wp.pl', 'GOsGemJarMJu8btZKF6Rung27JLZkdO7Wfd4CwLhL1k=','Admin'"; + + + SqlConnection connection = new SqlConnection(connectionString); + connection.Open(); + + SqlCommand command = new SqlCommand(queryUser, connection); + command.CommandTimeout = 200; + command.ExecuteNonQuery(); + connection.Close(); + + + SqlConnection connection2 = new SqlConnection(connectionString); + connection.Open(); + + SqlCommand command2 = new SqlCommand(queryAdmin, connection); + command2.CommandTimeout = 200; + command2.ExecuteNonQuery(); + connection2.Close(); + + } + + } + catch (Exception e) + { + Console.WriteLine("Nie udało się dodać kont użytkowników " + e.Message); + } + - - try { -- 2.20.1 From e2cab45690d066d8921b3d9ac3c3f15541fdb5d9 Mon Sep 17 00:00:00 2001 From: Maciej Maciejewski Date: Sat, 26 Oct 2024 21:17:52 +0200 Subject: [PATCH 4/4] autoryzacja --- Controllers/ExpenseController.cs | 7 +++++++ Controllers/ProductController.cs | 6 +++++- Controllers/ReportController.cs | 9 +++++++++ Controllers/TransactionController.cs | 7 +++++++ Controllers/UserController.cs | 26 +++++++++++++++++++------- 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/Controllers/ExpenseController.cs b/Controllers/ExpenseController.cs index f182ea3..ae9a342 100644 --- a/Controllers/ExpenseController.cs +++ b/Controllers/ExpenseController.cs @@ -17,11 +17,13 @@ using FirmTracker_Server.nHibernate.Expenses; using FirmTracker_Server.nHibernate.Products; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace FirmTracker_Server.Controllers { [Route("api/[controller]")] [ApiController] + [Authorize] public class ExpensesController : ControllerBase { private readonly ExpenseCRUD _expenseCrud; @@ -34,6 +36,7 @@ namespace FirmTracker_Server.Controllers [HttpPost] [ProducesResponseType(201)] // Created [ProducesResponseType(400)] // Bad Request + [Authorize(Roles = Roles.Admin)] public IActionResult CreateExpense([FromBody] Expense expense) { try { @@ -59,6 +62,7 @@ namespace FirmTracker_Server.Controllers [HttpGet("{id}")] [ProducesResponseType(200)] // Created [ProducesResponseType(404)] // Bad Request + [Authorize(Roles = Roles.Admin)] public IActionResult GetExpense(int id) { var expense = _expenseCrud.GetExpense(id); @@ -73,6 +77,7 @@ namespace FirmTracker_Server.Controllers [HttpPut("{id}")] [ProducesResponseType(204)] [ProducesResponseType(400)] + [Authorize(Roles = Roles.Admin)] public IActionResult UpdateExpense(int id, [FromBody] Expense expense) { try @@ -103,6 +108,7 @@ namespace FirmTracker_Server.Controllers [HttpDelete("{id}")] [ProducesResponseType(204)] [ProducesResponseType(404)] + [Authorize(Roles = Roles.Admin)] public IActionResult DeleteExpense(int id) { try @@ -123,6 +129,7 @@ namespace FirmTracker_Server.Controllers [HttpGet] [ProducesResponseType(200)] [ProducesResponseType(400)] + [Authorize(Roles = Roles.Admin)] public IActionResult GetAllExpenses() { try diff --git a/Controllers/ProductController.cs b/Controllers/ProductController.cs index e44a3ca..11cc479 100644 --- a/Controllers/ProductController.cs +++ b/Controllers/ProductController.cs @@ -42,7 +42,7 @@ namespace FirmTracker_Server.Controllers [HttpPost] [ProducesResponseType(200)] // Created [ProducesResponseType(400)] // Bad Request - [Authorize(Roles = Roles.User)] + [Authorize(Roles = Roles.Admin)] public IActionResult CreateProduct([FromBody] Product product) { try @@ -81,6 +81,7 @@ namespace FirmTracker_Server.Controllers [HttpGet("{id}")] [ProducesResponseType(200)] // Created [ProducesResponseType(400)] // Bad Request + [Authorize(Roles=Roles.Admin+","+Roles.User)] public IActionResult GetProduct(int id) { var product = _productCrud.GetProduct(id); @@ -92,6 +93,7 @@ namespace FirmTracker_Server.Controllers [HttpGet("name/{name}")] [ProducesResponseType(200)] [ProducesResponseType(404)] + [Authorize(Roles = Roles.Admin + "," + Roles.User)] public IActionResult GetProductByName(string name) { var product = _productCrud.GetProductByName(name); @@ -104,6 +106,7 @@ namespace FirmTracker_Server.Controllers [HttpPut("{id}")] [ProducesResponseType(200)] // Created [ProducesResponseType(400)] // Bad Request + [Authorize(Roles = Roles.Admin + "," + Roles.User)] public IActionResult UpdateProduct(int id, [FromBody] Product product) { try @@ -145,6 +148,7 @@ namespace FirmTracker_Server.Controllers [HttpDelete("{id}")] [ProducesResponseType(200)] // Created [ProducesResponseType(400)] // Bad Request + [Authorize(Roles = Roles.Admin)] public IActionResult DeleteProduct(int id) { try diff --git a/Controllers/ReportController.cs b/Controllers/ReportController.cs index dabcd8e..5695d2b 100644 --- a/Controllers/ReportController.cs +++ b/Controllers/ReportController.cs @@ -24,12 +24,14 @@ using FirmTracker_Server.nHibernate.Expenses; using FirmTracker_Server.nHibernate.Products; using FirmTracker_Server.nHibernate; using NHibernate.Linq; +using Microsoft.AspNetCore.Authorization; namespace FirmTracker_Server.Controllers { [Route("api/[controller]")] [ApiController] + [Authorize] public class ReportController : ControllerBase { private readonly ReportCRUD _reportCRUD; @@ -43,6 +45,7 @@ namespace FirmTracker_Server.Controllers [HttpPost] [ProducesResponseType(201)] //Created [ProducesResponseType(400)] //Bad request + [Authorize(Roles = Roles.Admin)] public IActionResult CreateReport([FromBody] Report.DateRangeDto dateRange) { try @@ -118,6 +121,7 @@ namespace FirmTracker_Server.Controllers [HttpGet("{id}")] [ProducesResponseType(200)] [ProducesResponseType(404)] + [Authorize(Roles = Roles.Admin)] public IActionResult GetReport(int id) { var report = _reportCRUD.GetReport(id); @@ -136,6 +140,7 @@ namespace FirmTracker_Server.Controllers [HttpGet("{id}/transactions")] [ProducesResponseType(200)] [ProducesResponseType(404)] + [Authorize(Roles = Roles.Admin)] public IActionResult GetReportTransactions(int id) { var transactions = _reportCRUD.GetReportTransactions(id); @@ -149,6 +154,7 @@ namespace FirmTracker_Server.Controllers [HttpGet("{id}/expenses")] [ProducesResponseType(200)] [ProducesResponseType(404)] + [Authorize(Roles = Roles.Admin)] public IActionResult GetReportExpenses(int id) { var expenses = _reportCRUD.GetReportExpenses(id); @@ -163,6 +169,7 @@ namespace FirmTracker_Server.Controllers [HttpGet] [ProducesResponseType(200)] [ProducesResponseType(404)] + [Authorize(Roles = Roles.Admin)] public IActionResult GetAllReports() { var reports = _reportCRUD.GetAllReports(); @@ -176,6 +183,7 @@ namespace FirmTracker_Server.Controllers [ProducesResponseType(204)] [ProducesResponseType(400)] [ProducesResponseType(404)] + [Authorize(Roles = Roles.Admin)] public IActionResult UpdateReport(int id, [FromBody] Report.DateRangeDto dateRange) { try @@ -244,6 +252,7 @@ namespace FirmTracker_Server.Controllers [HttpDelete("{id}")] [ProducesResponseType(204)] [ProducesResponseType(404)] + [Authorize(Roles = Roles.Admin)] public IActionResult DeleteReport(int id) { try diff --git a/Controllers/TransactionController.cs b/Controllers/TransactionController.cs index 20b556e..276a50a 100644 --- a/Controllers/TransactionController.cs +++ b/Controllers/TransactionController.cs @@ -24,11 +24,13 @@ using System.Transactions; using FirmTracker_Server.nHibernate.Products; using FirmTracker_Server.nHibernate; using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Authorization; namespace FirmTracker_Server.Controllers { [Route("api/[controller]")] [ApiController] + [Authorize] public class TransactionController : ControllerBase { private readonly TransactionCRUD _transactionCRUD; @@ -48,6 +50,7 @@ namespace FirmTracker_Server.Controllers [HttpPost] [ProducesResponseType(StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(Roles = Roles.Admin + "," + Roles.User)] public IActionResult CreateTransaction([FromBody] nHibernate.Transactions.Transaction transaction) { try @@ -106,6 +109,7 @@ namespace FirmTracker_Server.Controllers [HttpGet("{id}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [Authorize(Roles = Roles.Admin + "," + Roles.User)] public IActionResult GetTransaction(int id) { var transaction = _transactionCRUD.GetTransaction(id); @@ -118,6 +122,7 @@ namespace FirmTracker_Server.Controllers [HttpPut("{id}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(Roles = Roles.Admin + "," + Roles.User)] public IActionResult UpdateTransaction(int id, [FromBody] nHibernate.Transactions.Transaction transaction) { if (id != transaction.Id) @@ -160,6 +165,7 @@ namespace FirmTracker_Server.Controllers [HttpDelete("{id}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [Authorize(Roles = Roles.Admin + "," + Roles.User)] public IActionResult DeleteTransaction(int id) { try @@ -182,6 +188,7 @@ namespace FirmTracker_Server.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [Authorize(Roles = Roles.Admin + "," + Roles.User)] public IActionResult GetAllTransactions() { var transactions = _transactionCRUD.GetAllTransactions(); diff --git a/Controllers/UserController.cs b/Controllers/UserController.cs index 4175696..77e437a 100644 --- a/Controllers/UserController.cs +++ b/Controllers/UserController.cs @@ -4,6 +4,7 @@ using FirmTracker_Server; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using FirmTracker_Server.Entities; +using System.Security.Claims; namespace FirmTracker_Server.Controllers { @@ -38,13 +39,24 @@ namespace FirmTracker_Server.Controllers var token = UserService.CreateTokenJwt(dto); return Ok(token); } - // New method to get all users - /* [HttpGet("all")] - [AllowAnonymous] - public ActionResult> GetAllUsers() + [HttpGet("role")] + [Authorize(Roles = Roles.Admin + "," + Roles.User)] + public ActionResult GetUserRole() { - var users = UserService.GetAllUsers(); - return Ok(users); - }*/ + var roleClaim = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value; + if (roleClaim == null) + { + return NotFound("Role not found for the logged-in user."); + } + return Ok(roleClaim); + } + // New method to get all users + /* [HttpGet("all")] + [AllowAnonymous] + public ActionResult> GetAllUsers() + { + var users = UserService.GetAllUsers(); + return Ok(users); + }*/ } } -- 2.20.1