| @@ -0,0 +1,4 @@ | |||
| [*.cs] | |||
| # CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. | |||
| dotnet_diagnostic.CS8618.severity = none | |||
| @@ -0,0 +1,17 @@ | |||
| ################################################################################ | |||
| # This .gitignore file was automatically created by Microsoft(R) Visual Studio. | |||
| ################################################################################ | |||
| /.vs | |||
| /Diligent.WebAPI.Data/bin/Debug/net6.0 | |||
| /Diligent.WebAPI.Data/obj | |||
| /Diligent.WebAPI.Host/.vs/Diligent.WebAPI/v17 | |||
| /Diligent.WebAPI.Host/bin/Debug/net6.0 | |||
| /Diligent.WebAPI.Host/obj | |||
| /Diligent.WebAPI.Host/Logs | |||
| /Diligent.WebAPI.Business/bin/Debug/net6.0 | |||
| /Diligent.WebAPI.Business/obj/Debug/net6.0 | |||
| /Diligent.WebAPI.Business/obj | |||
| /Diligent.WebAPI.Contracts/bin/Debug/net6.0 | |||
| /Diligent.WebAPI.Contracts/obj/Debug/net6.0 | |||
| /Diligent.WebAPI.Contracts/obj | |||
| @@ -0,0 +1,20 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <TargetFramework>net6.0</TargetFramework> | |||
| <ImplicitUsings>enable</ImplicitUsings> | |||
| <Nullable>enable</Nullable> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="AutoMapper" Version="11.0.1" /> | |||
| <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" /> | |||
| <PackageReference Include="RestSharp" Version="108.0.2-alpha.0.6" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\Diligent.WebAPI.Contracts\Diligent.WebAPI.Contracts.csproj" /> | |||
| <ProjectReference Include="..\Diligent.WebAPI.Data\Diligent.WebAPI.Data.csproj" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,19 @@ | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class CompanyMappingProfile : Profile | |||
| { | |||
| public CompanyMappingProfile() | |||
| { | |||
| #region Models to DTOs | |||
| CreateMap<InsuranceCompany, InsuranceCompanyViewDto>(); | |||
| #endregion | |||
| #region DTOs to Models | |||
| CreateMap<InsuranceCompanyCreateDto, InsuranceCompany>(); | |||
| CreateMap<InsuranceCompanyUpdateDto, InsuranceCompany>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class InsurerMappingProfile : Profile | |||
| { | |||
| public InsurerMappingProfile() | |||
| { | |||
| #region DTO to Model | |||
| CreateMap<InsurerCreateDto, Insurer>(); | |||
| CreateMap<InsurerUpdateDto, Insurer>(); | |||
| #endregion | |||
| #region Model to DTO | |||
| CreateMap<Insurer, InsurerViewDto>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,12 @@ | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class PolicyMappingProfiles : Profile | |||
| { | |||
| public PolicyMappingProfiles() | |||
| { | |||
| CreateMap<InsurancePolicy, InsurancePolicyViewDto>(); | |||
| CreateMap<InsurancePolicyCreateDto, InsurancePolicy>(); | |||
| CreateMap<InsurancePolicyUpdateDto, InsurancePolicy>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,16 @@ | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class WebhookMappingProfile : Profile | |||
| { | |||
| public WebhookMappingProfile() | |||
| { | |||
| #region DTO to Model | |||
| CreateMap<WebhookSubscriptionCreateDto, WebhookSubscription>(); | |||
| #endregion | |||
| #region Model to DTO | |||
| CreateMap<WebhookDefinition, WebhookDefinitionViewDto>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,61 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class InsuranceCompaniesService : IInsuranceCompaniesService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| public InsuranceCompaniesService(DatabaseContext context, IMapper mapper) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| } | |||
| public async Task<List<InsuranceCompanyViewDto>> GetInsuranceCompanies() | |||
| { | |||
| var insuranceCompanies = await _context.InsuranceCompanies.ToListAsync(); | |||
| var insuranceCompaniesDto = _mapper.Map<List<InsuranceCompanyViewDto>>(insuranceCompanies); | |||
| return insuranceCompaniesDto; | |||
| } | |||
| public async Task<InsuranceCompanyViewDto?> GetInsuranceCompany(long id) | |||
| { | |||
| var insuranceCompany = await _context.InsuranceCompanies.FindAsync(id); | |||
| if (insuranceCompany == null) | |||
| throw new EntityNotFoundException("Insurance company not found"); | |||
| var insuranceCompanyDto = _mapper.Map<InsuranceCompanyViewDto?>(insuranceCompany); | |||
| return insuranceCompanyDto; | |||
| } | |||
| public async Task CreateInsuranceCompany(InsuranceCompanyCreateDto insuranceCompanyCreateDto) | |||
| { | |||
| var insuranceCompany = _mapper.Map<InsuranceCompany>(insuranceCompanyCreateDto); | |||
| insuranceCompany.CreatedAtUtc = DateTime.UtcNow; | |||
| await _context.InsuranceCompanies.AddAsync(insuranceCompany); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task UpdateInsuranceCompany(long insuranceCompanyId, InsuranceCompanyUpdateDto insuranceCompanyUpdateDto) | |||
| { | |||
| var insuranceCompany = _context.InsuranceCompanies.Find(insuranceCompanyId); | |||
| if (insuranceCompany == null) | |||
| throw new EntityNotFoundException($"Insurance company not found"); | |||
| _mapper.Map(insuranceCompanyUpdateDto, insuranceCompany); | |||
| insuranceCompany.UpdatedAtUtc = DateTime.UtcNow; | |||
| _context.Entry(insuranceCompany).State = EntityState.Modified; | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task DeleteInsuranceCompany(long insuranceCompanyId) | |||
| { | |||
| var insuranceCompany = _context.InsuranceCompanies.Find(insuranceCompanyId); | |||
| if (insuranceCompany == null) | |||
| throw new EntityNotFoundException("Insurance company not found"); | |||
| _context.Remove(insuranceCompany); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,73 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class InsurancePoliciesService : IInsurancePoliciesService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IWebhookPublisherService _webhookPublisher; | |||
| private readonly IMapper _mapper; | |||
| public InsurancePoliciesService(DatabaseContext context, IWebhookPublisherService webhookPublisher, IMapper mapper) | |||
| { | |||
| _context = context; | |||
| _webhookPublisher = webhookPublisher; | |||
| _mapper = mapper; | |||
| } | |||
| public async Task<List<InsurancePolicyViewDto>> GetInsurancePolicies() | |||
| { | |||
| var insurancePolicies = await _context.InsurancePolicies | |||
| .Include(i => i.Insurer) | |||
| .ThenInclude(k => k.InsuranceCompany) | |||
| .ToListAsync(); | |||
| var insurancePoliciesDto = _mapper.Map<List<InsurancePolicyViewDto>>(insurancePolicies); | |||
| return insurancePoliciesDto; | |||
| } | |||
| public async Task<InsurancePolicyViewDto?> GetInsurancePolicy(long id) | |||
| { | |||
| var insurancePolicy = await _context.InsurancePolicies | |||
| .Include(i => i.Insurer) | |||
| .ThenInclude(k => k.InsuranceCompany) | |||
| .FirstOrDefaultAsync(i => i.Id == id); | |||
| if (insurancePolicy == null) | |||
| throw new EntityNotFoundException("Insurance policy not found"); | |||
| var insurancePolicyDto = _mapper.Map<InsurancePolicyViewDto>(insurancePolicy); | |||
| return insurancePolicyDto; | |||
| } | |||
| public async Task CreateInsurancePolicy(InsurancePolicyCreateDto insurancePolicyCreateDto) | |||
| { | |||
| var insurancePolicy = _mapper.Map<InsurancePolicy>(insurancePolicyCreateDto); | |||
| var result = await _context.InsurancePolicies.AddAsync(insurancePolicy); | |||
| await _webhookPublisher.PublishAsync("insurancePolicy.created", result); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task UpdateInsurancePolicy(long insurancePolicyId, InsurancePolicyUpdateDto insurancePolicyUpdateDto) | |||
| { | |||
| var insurancePolicy = _context.InsurancePolicies.Find(insurancePolicyId); | |||
| if (insurancePolicy == null) | |||
| throw new EntityNotFoundException("Insurance policy not found"); | |||
| _mapper.Map(insurancePolicyUpdateDto, insurancePolicy); | |||
| insurancePolicy.UpdatedAtUtc = DateTime.UtcNow; | |||
| _context.Entry(insurancePolicy).State = EntityState.Modified; | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task DeleteInsurancePolicy(long insurancePolicyId) | |||
| { | |||
| var insurancePolicy = _context.InsurancePolicies.Find(insurancePolicyId); | |||
| if (insurancePolicy == null) | |||
| throw new EntityNotFoundException("Insurance policy not found"); | |||
| _context.Remove(insurancePolicy); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,63 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class InsurersService : IInsurersService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| public InsurersService(DatabaseContext context, IMapper mapper) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| } | |||
| public async Task<List<InsurerViewDto>> GetInsurers() | |||
| { | |||
| var insurers = await _context.Insurers.Include(x => x.InsuranceCompany).ToListAsync(); | |||
| return _mapper.Map<List<InsurerViewDto>>(insurers); | |||
| } | |||
| public async Task<InsurerViewDto?> GetInsurer(long id) | |||
| { | |||
| var insurer = await _context.Insurers | |||
| .Include(x => x.InsuranceCompany) | |||
| .FirstOrDefaultAsync(x => x.Id == id); | |||
| if (insurer == null) | |||
| throw new EntityNotFoundException("Insurer not found"); | |||
| return _mapper.Map<InsurerViewDto>(insurer); | |||
| } | |||
| public async Task CreateInsurer(InsurerCreateDto insurerCreateDto) | |||
| { | |||
| var insurer = _mapper.Map<Insurer>(insurerCreateDto); | |||
| await _context.Insurers.AddAsync(insurer); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task UpdateInsurer(long insurerId, InsurerUpdateDto insurerUpdateDto) | |||
| { | |||
| var insurer = _context.InsurancePolicies.Find(insurerId); | |||
| if (insurer == null) | |||
| throw new EntityNotFoundException("Insurer not found"); | |||
| _mapper.Map(insurerUpdateDto, insurer); | |||
| insurer.UpdatedAtUtc = DateTime.UtcNow; | |||
| _context.Entry(insurer).State = EntityState.Modified; | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task DeleteInsurerAsync(long insurerId) | |||
| { | |||
| var insurer = _context.InsurancePolicies.Find(insurerId); | |||
| if (insurer == null) | |||
| throw new EntityNotFoundException("Insurer not found"); | |||
| _context.Remove(insurer); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,13 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IInsuranceCompaniesService | |||
| { | |||
| Task<List<InsuranceCompanyViewDto>> GetInsuranceCompanies(); | |||
| Task<InsuranceCompanyViewDto?> GetInsuranceCompany(long id); | |||
| Task CreateInsuranceCompany(InsuranceCompanyCreateDto insuranceCompanyCreateDto); | |||
| Task UpdateInsuranceCompany(long insuranceCompanyId, InsuranceCompanyUpdateDto insuranceCompanyUpdateDto); | |||
| Task DeleteInsuranceCompany(long insuranceCompanyId); | |||
| } | |||
| } | |||
| @@ -0,0 +1,15 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IInsurancePoliciesService | |||
| { | |||
| Task<List<InsurancePolicyViewDto>> GetInsurancePolicies(); | |||
| Task<InsurancePolicyViewDto?> GetInsurancePolicy(long id); | |||
| Task CreateInsurancePolicy(InsurancePolicyCreateDto insurancePolicyCreateDto); | |||
| Task UpdateInsurancePolicy(long insurancePolicyId, InsurancePolicyUpdateDto insurancePolicyUpdateDto); | |||
| Task DeleteInsurancePolicy(long insurancePolicyId); | |||
| } | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IInsurersService | |||
| { | |||
| Task<List<InsurerViewDto>> GetInsurers(); | |||
| Task<InsurerViewDto?> GetInsurer(long id); | |||
| Task CreateInsurer(InsurerCreateDto insurerCreateDto); | |||
| Task UpdateInsurer(long insurerId, InsurerUpdateDto insurerUpdateDto); | |||
| Task DeleteInsurerAsync(long insurerId); | |||
| } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IUserService | |||
| { | |||
| AuthenticateResponseDto? Authenticate(AuthenticateRequestDto model); | |||
| IEnumerable<User?> GetAll(); | |||
| User? GetById(int id); | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IWebhookDefinitionService | |||
| { | |||
| /// <summary> | |||
| /// Get all webhook definitions | |||
| /// </summary> | |||
| Task<List<WebhookDefinitionViewDto>> GetAll(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,7 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IWebhookPublisherService | |||
| { | |||
| Task PublishAsync(string webhookName, object data); | |||
| } | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IWebhookSubscriptionService | |||
| { | |||
| /// <summary> | |||
| /// Create new webhook subscription | |||
| /// </summary> | |||
| Task<WebhookSubscription> CreateWebhookSubscription(WebhookSubscriptionCreateDto dto); | |||
| /// <summary> | |||
| /// Get subscriptions by webhook name | |||
| /// </summary> | |||
| Task<List<WebhookSubscription>> GetAllSubscriptionsAsync(string webhookName); | |||
| } | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class UserService : IUserService | |||
| { | |||
| private readonly AuthorizationSettings _authSettings; | |||
| public UserService(IOptions<AuthorizationSettings> authSettings) | |||
| { | |||
| _authSettings = authSettings.Value; | |||
| } | |||
| // User list for testing | |||
| private readonly List<User> _users = new List<User> | |||
| { | |||
| new User { Id = 1, FirstName = "Test", LastName = "User", Username = "test", Password = "test" } | |||
| }; | |||
| public AuthenticateResponseDto? Authenticate(AuthenticateRequestDto model) | |||
| { | |||
| var user = _users.SingleOrDefault(x => x.Username == model.Username && x.Password == model.Password); | |||
| // return null if user not found | |||
| if (user == null) | |||
| return null; | |||
| // authentication successful so generate jwt token | |||
| var token = GenerateJwtToken(user); | |||
| return new AuthenticateResponseDto | |||
| { | |||
| Id = user.Id, | |||
| Username = user.Username, | |||
| FirstName = user.FirstName, | |||
| LastName = user.LastName, | |||
| Token = token | |||
| }; | |||
| } | |||
| public IEnumerable<User> GetAll() | |||
| { | |||
| return _users; | |||
| } | |||
| public User? GetById(int id) | |||
| { | |||
| return _users.FirstOrDefault(x => x.Id == id); | |||
| } | |||
| private string GenerateJwtToken(User user) | |||
| { | |||
| // generate token that is valid for 7 days | |||
| var tokenHandler = new JwtSecurityTokenHandler(); | |||
| var key = Encoding.ASCII.GetBytes(_authSettings.Secret); | |||
| var tokenDescriptor = new SecurityTokenDescriptor | |||
| { | |||
| Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()) }), | |||
| Expires = DateTime.UtcNow.AddMinutes(2), | |||
| SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) | |||
| }; | |||
| var token = tokenHandler.CreateToken(tokenDescriptor); | |||
| return tokenHandler.WriteToken(token); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,20 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class WebhookDefinitionService : IWebhookDefinitionService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| public WebhookDefinitionService(DatabaseContext context, IMapper mapper) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| } | |||
| public async Task<List<WebhookDefinitionViewDto>> GetAll() | |||
| { | |||
| var webhookDefinitions = await _context.WebhookDefinitions.ToListAsync(); | |||
| return _mapper.Map<List<WebhookDefinitionViewDto>>(webhookDefinitions); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class WebhookPublisherService : IWebhookPublisherService | |||
| { | |||
| private readonly IWebhookSubscriptionService _subscriptionService; | |||
| public WebhookPublisherService(IWebhookSubscriptionService subscriptionService) | |||
| { | |||
| _subscriptionService = subscriptionService; | |||
| } | |||
| public async Task PublishAsync(string webhookName, object data) | |||
| { | |||
| // Get all subscriptions | |||
| var subscriptions = await _subscriptionService.GetAllSubscriptionsAsync(webhookName); | |||
| if (subscriptions == null || subscriptions.Count == 0) | |||
| return; | |||
| // Send POST request to subscriptions | |||
| // 1: define POST request | |||
| var request = new RestRequest("", Method.Post); | |||
| // 2: define request body | |||
| var serializedOrder = JsonConvert.SerializeObject(data, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); | |||
| request.AddJsonBody(serializedOrder); | |||
| // 3: define request headers | |||
| request.AddHeader("Content-Type", "application/json"); | |||
| foreach (var subscription in subscriptions) | |||
| { | |||
| try | |||
| { | |||
| // 4: define client endpoint | |||
| var client = new RestClient(subscription.WebhookURL); | |||
| // 5: send | |||
| await client.ExecuteAsync(request); | |||
| } | |||
| catch (Exception) | |||
| { | |||
| // if one subscription fail continue | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,36 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class WebhookSubscriptionService : IWebhookSubscriptionService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| public WebhookSubscriptionService(DatabaseContext context, IMapper mapper) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| } | |||
| public async Task<WebhookSubscription> CreateWebhookSubscription(WebhookSubscriptionCreateDto dto) | |||
| { | |||
| // map dto to db model | |||
| WebhookSubscription subscription = _mapper.Map<WebhookSubscription>(dto); | |||
| subscription.CreatedAtUtc = DateTime.UtcNow; | |||
| subscription.IsActive = true; | |||
| // add to db | |||
| await _context.WebhookSubscriptions.AddAsync(subscription); | |||
| await _context.SaveChangesAsync(); | |||
| return subscription; | |||
| } | |||
| public async Task<List<WebhookSubscription>> GetAllSubscriptionsAsync(string webhookName) | |||
| { | |||
| return await _context.WebhookSubscriptions | |||
| .Where(x => x.WebhookDefinition.Name == webhookName) | |||
| .Include(x => x.WebhookDefinition) | |||
| .ToListAsync(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,7 @@ | |||
| namespace Diligent.WebAPI.Business.Settings | |||
| { | |||
| public class AuthorizationSettings | |||
| { | |||
| public string Secret { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,25 @@ | |||
| global using Diligent.WebAPI.Business.Services.Interfaces; | |||
| global using Diligent.WebAPI.Business.Settings; | |||
| global using Diligent.WebAPI.Data; | |||
| global using Diligent.WebAPI.Data.Entities; | |||
| global using Diligent.WebAPI.Contracts.DTOs.InsuranceCompany; | |||
| global using Diligent.WebAPI.Contracts.DTOs.InsurancePolicy; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Insurer; | |||
| global using Diligent.WebAPI.Contracts.DTOs.WebhookDefinition; | |||
| global using Diligent.WebAPI.Contracts.DTOs.WebhookSubscription; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Auth; | |||
| global using Diligent.WebAPI.Contracts.Exceptions; | |||
| global using Microsoft.EntityFrameworkCore; | |||
| global using Microsoft.Extensions.Options; | |||
| global using Microsoft.IdentityModel.Tokens; | |||
| global using System.IdentityModel.Tokens.Jwt; | |||
| global using System.Security.Claims; | |||
| global using System.Text; | |||
| global using Newtonsoft.Json; | |||
| global using RestSharp; | |||
| global using AutoMapper; | |||
| @@ -0,0 +1,11 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Auth | |||
| { | |||
| public class AuthenticateRequestDto | |||
| { | |||
| [Required] | |||
| public string Username { get; set; } | |||
| [Required] | |||
| public string Password { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Auth | |||
| { | |||
| public class AuthenticateResponseDto | |||
| { | |||
| public long Id { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public string Username { get; set; } | |||
| public string Token { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,19 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Error | |||
| { | |||
| public class ErrorResponseDto | |||
| { | |||
| public string Message { get; set; } | |||
| public List<ValidationItemDto> ValidationItems { get; set; } = new List<ValidationItemDto>(); | |||
| public ErrorResponseDto(string message) | |||
| { | |||
| Message = message; | |||
| } | |||
| public ErrorResponseDto(string message, List<ValidationItemDto> validationItems) | |||
| { | |||
| Message = message; | |||
| ValidationItems = validationItems; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Error | |||
| { | |||
| public class ValidationItemDto | |||
| { | |||
| public string Key { get; set; } | |||
| public string? Value { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,19 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsuranceCompany | |||
| { | |||
| public class InsuranceCompanyCreateDto | |||
| { | |||
| [Required] | |||
| public string Name { get; set; } | |||
| [DataType(DataType.PhoneNumber)] | |||
| [RegularExpression(@"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Not a valid phone number")] | |||
| public string? PhoneNumber { get; set; } | |||
| public string? Fax { get; set; } | |||
| public string? City { get; set; } | |||
| public string? Country { get; set; } | |||
| [RegularExpression(@"^\d{5}(-\d{4})?$", ErrorMessage = "Invalid Postal Code")] | |||
| public string? PostalCode { get; set; } | |||
| public string? LegalAddress { get; set; } | |||
| [RegularExpression(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$", ErrorMessage = "Invalid email address")] | |||
| public string? LegalEmail { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsuranceCompany | |||
| { | |||
| public class InsuranceCompanyUpdateDto | |||
| { | |||
| public string Name { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string Fax { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string LegalAddress { get; set; } | |||
| public string LegalEmail { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,18 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsuranceCompany | |||
| { | |||
| public class InsuranceCompanyViewDto | |||
| { | |||
| public long Id { get; set; } | |||
| public DateTime CreatedAtUtc { get; set; } | |||
| public DateTime? UpdatedAtUtc { get; set; } | |||
| public DateTime? DeletedAtUtc { get; set; } | |||
| public string Name { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string Fax { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string LegalAddress { get; set; } | |||
| public string LegalEmail { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsurancePolicy | |||
| { | |||
| public class InsurancePolicyCreateDto | |||
| { | |||
| public decimal Premium { get; set; } | |||
| public DateTime StartDate { get; set; } | |||
| public DateTime EndDate { get; set; } | |||
| public string Type { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsurancePolicy | |||
| { | |||
| public class InsurancePolicyUpdateDto | |||
| { | |||
| public decimal Premium { get; set; } | |||
| public DateTime StartDate { get; set; } | |||
| public DateTime EndDate { get; set; } | |||
| public string Type { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsurancePolicy | |||
| { | |||
| public class InsurancePolicyViewDto | |||
| { | |||
| public int Id { get; set; } | |||
| public decimal Premium { get; set; } | |||
| public DateTime StartDate { get; set; } | |||
| public DateTime EndDate { get; set; } | |||
| public string Type { get; set; } | |||
| //public long InsurerId { get; set; } | |||
| //public virtual Insurer Insurer { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Insurer | |||
| { | |||
| public class InsurerCreateDto | |||
| { | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public DateTime DateOfBirth { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string Address { get; set; } | |||
| public string Email { get; set; } | |||
| public long InsuranceCompanyId { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Insurer | |||
| { | |||
| public class InsurerUpdateDto | |||
| { | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public DateTime DateOfBirth { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string Address { get; set; } | |||
| public string Email { get; set; } | |||
| public long InsuranceCompanyId { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,18 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Insurer | |||
| { | |||
| public class InsurerViewDto | |||
| { | |||
| public long Id { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public DateTime DateOfBirth { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string Address { get; set; } | |||
| public string Email { get; set; } | |||
| public InsuranceCompanyViewDto InsuranceCompany { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.WebhookDefinition | |||
| { | |||
| public class WebhookDefinitionViewDto | |||
| { | |||
| public long Id { get; set; } | |||
| public string Name { get; set; } | |||
| public string DisplayName { get; set; } | |||
| public string Description { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.WebhookSubscription | |||
| { | |||
| public class WebhookSubscriptionCreateDto | |||
| { | |||
| [Required] | |||
| public string WebhookUri { get; set; } | |||
| [Required] | |||
| public long WebhookDefinitionId { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,13 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <TargetFramework>net6.0</TargetFramework> | |||
| <ImplicitUsings>enable</ImplicitUsings> | |||
| <Nullable>enable</Nullable> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\Diligent.WebAPI.Data\Diligent.WebAPI.Data.csproj" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,25 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.Exceptions | |||
| { | |||
| public class EntityNotFoundException : Exception | |||
| { | |||
| public EntityNotFoundException() | |||
| { | |||
| } | |||
| public EntityNotFoundException(string message) | |||
| : base(message) | |||
| { | |||
| } | |||
| public EntityNotFoundException(string message, Exception inner) | |||
| : base(message, inner) | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,39 @@ | |||
| namespace Diligent.WebAPI.Contracts.Models | |||
| { | |||
| public class BaseResult<T> where T : class | |||
| { | |||
| public bool IsSuccess { get; set; } = true; | |||
| public T DataObject { get; set; } | |||
| public IList<ResultError> Errors { get; set; } = new List<ResultError>(); | |||
| public void Add400BadRequestError(string name, string message) | |||
| { | |||
| var error = new ResultError() | |||
| { | |||
| Name = name | |||
| }; | |||
| error.Add400BadRequestError(message); | |||
| Errors.Add(error); | |||
| } | |||
| public void Add404NotFoundError(string name, string message) | |||
| { | |||
| var error = new ResultError() | |||
| { | |||
| Name = name | |||
| }; | |||
| error.Add404NotFoundError(message); | |||
| Errors.Add(error); | |||
| } | |||
| public void Add409ConflictError(string name, string message) | |||
| { | |||
| var error = new ResultError() | |||
| { | |||
| Name = name | |||
| }; | |||
| error.Add409ConflictError(message); | |||
| Errors.Add(error); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| namespace Diligent.WebAPI.Contracts.Models | |||
| { | |||
| public class HttpResultError | |||
| { | |||
| public HttpStatusCode ErrorCode { get; set; } | |||
| public string ErrorMessage { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| namespace Diligent.WebAPI.Contracts.Models | |||
| { | |||
| public class ResultError | |||
| { | |||
| public string Name { get; set; } | |||
| public IList<HttpResultError> Messages { get; set; } = new List<HttpResultError>(); | |||
| public ResultError() | |||
| { | |||
| } | |||
| public ResultError(string name) | |||
| { | |||
| Name = name; | |||
| } | |||
| public void Add400BadRequestError(string message) | |||
| { | |||
| Messages.Add(new HttpResultError | |||
| { | |||
| ErrorCode = HttpStatusCode.BadRequest, | |||
| ErrorMessage = message | |||
| }); | |||
| } | |||
| public void Add404NotFoundError(string message) | |||
| { | |||
| Messages.Add(new HttpResultError | |||
| { | |||
| ErrorCode = HttpStatusCode.NotFound, | |||
| ErrorMessage = message | |||
| }); | |||
| } | |||
| public void Add409ConflictError(string message) | |||
| { | |||
| Messages.Add(new HttpResultError | |||
| { | |||
| ErrorCode = HttpStatusCode.Conflict, | |||
| ErrorMessage = message | |||
| }); | |||
| } | |||
| public void AddCustomError(HttpResultError error) | |||
| { | |||
| Messages.Add(error); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,3 @@ | |||
| global using System.Net; | |||
| global using Diligent.WebAPI.Contracts.DTOs.InsuranceCompany; | |||
| global using System.ComponentModel.DataAnnotations; | |||
| @@ -0,0 +1,17 @@ | |||
| namespace Diligent.WebAPI.Data; | |||
| public class DatabaseContext : DbContext | |||
| { | |||
| public DbSet<InsuranceCompany> InsuranceCompanies { get; set; } | |||
| public DbSet<Insurer> Insurers { get; set; } | |||
| public DbSet<InsurancePolicy> InsurancePolicies { get; set; } | |||
| public DbSet<WebhookSubscription> WebhookSubscriptions { get; set; } | |||
| public DbSet<WebhookDefinition> WebhookDefinitions { get; set; } | |||
| public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { } | |||
| protected override void OnModelCreating(ModelBuilder modelBuilder) | |||
| { | |||
| base.OnModelCreating(modelBuilder); | |||
| } | |||
| } | |||
| @@ -0,0 +1,24 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <TargetFramework>net6.0</TargetFramework> | |||
| <ImplicitUsings>enable</ImplicitUsings> | |||
| <Nullable>enable</Nullable> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="AutoMapper" Version="11.0.1" /> | |||
| <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" /> | |||
| <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" /> | |||
| <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.3" /> | |||
| <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.3"> | |||
| <PrivateAssets>all</PrivateAssets> | |||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | |||
| </PackageReference> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Folder Include="Migrations\" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Diligent.WebAPI.Data.Entities; | |||
| public class Base | |||
| { | |||
| public long Id { get; set; } | |||
| public DateTime CreatedAtUtc { get; set; } | |||
| public DateTime? UpdatedAtUtc { get; set; } | |||
| public DateTime? DeletedAtUtc { get; set; } | |||
| } | |||
| @@ -0,0 +1,13 @@ | |||
| namespace Diligent.WebAPI.Data.Entities; | |||
| public class InsuranceCompany : Base | |||
| { | |||
| public string Name { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string Fax { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string LegalAddress { get; set; } | |||
| public string LegalEmail { get; set; } | |||
| } | |||
| @@ -0,0 +1,12 @@ | |||
| namespace Diligent.WebAPI.Data.Entities; | |||
| public class InsurancePolicy : Base | |||
| { | |||
| public decimal Premium { get; set; } | |||
| public DateTime StartDate { get; set; } | |||
| public DateTime EndDate { get; set; } | |||
| public string Type { get; set; } | |||
| public long InsurerId { get; set; } | |||
| public virtual Insurer Insurer { get; set; } | |||
| } | |||
| @@ -0,0 +1,18 @@ | |||
| namespace Diligent.WebAPI.Data.Entities; | |||
| public class Insurer : Base | |||
| { | |||
| [Required] | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public DateTime DateOfBirth { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string Address { get; set; } | |||
| public string Email { get; set; } | |||
| public long InsuranceCompanyId { get; set; } | |||
| public virtual InsuranceCompany InsuranceCompany { get; set; } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Diligent.WebAPI.Data.Entities; | |||
| public class User : Base | |||
| { | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public string Username { get; set; } | |||
| public string Password { get; set; } | |||
| } | |||
| @@ -0,0 +1,12 @@ | |||
| namespace Diligent.WebAPI.Data.Entities | |||
| { | |||
| public class WebhookDefinition : Base | |||
| { | |||
| [Required] | |||
| [MaxLength(100)] | |||
| public string Name { get; set; } // example: insuranceCompany.Created | |||
| [MaxLength(100)] | |||
| public string DisplayName { get; set; } | |||
| public string Description { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| namespace Diligent.WebAPI.Data.Entities | |||
| { | |||
| public class WebhookSubscription : Base | |||
| { | |||
| public string WebhookURL { get; set; } | |||
| public bool IsActive { get; set; } | |||
| public long WebhookDefinitionId { get; set; } | |||
| public virtual WebhookDefinition WebhookDefinition { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| namespace Diligent.WebAPI.Data.Extensions; | |||
| public static class ServiceCollection | |||
| { | |||
| public static void ConfigureData(this IServiceCollection services, IConfiguration configuration) | |||
| { | |||
| services.AddDbContext<DatabaseContext>(options => | |||
| { | |||
| if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development") | |||
| { | |||
| options.EnableSensitiveDataLogging(); | |||
| } | |||
| options.UseSqlServer(configuration.GetConnectionString(nameof(Diligent.WebAPI))); | |||
| }); | |||
| } | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| namespace Diligent.WebAPI.Data.Extensions; | |||
| public static class ServiceScope | |||
| { | |||
| public static void SetupData(this IServiceScope scope) | |||
| { | |||
| var dbContext = scope.ServiceProvider.GetRequiredService<DatabaseContext>(); | |||
| if (dbContext.Database.GetPendingMigrations().Any()) | |||
| { | |||
| dbContext.Database.Migrate(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,207 @@ | |||
| // <auto-generated /> | |||
| using System; | |||
| using Diligent.WebAPI.Data; | |||
| using Microsoft.EntityFrameworkCore; | |||
| using Microsoft.EntityFrameworkCore.Infrastructure; | |||
| using Microsoft.EntityFrameworkCore.Metadata; | |||
| using Microsoft.EntityFrameworkCore.Migrations; | |||
| using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | |||
| #nullable disable | |||
| namespace Diligent.WebAPI.Data.Migrations | |||
| { | |||
| [DbContext(typeof(DatabaseContext))] | |||
| [Migration("20220331142133_Initial")] | |||
| partial class Initial | |||
| { | |||
| protected override void BuildTargetModel(ModelBuilder modelBuilder) | |||
| { | |||
| #pragma warning disable 612, 618 | |||
| modelBuilder | |||
| .HasAnnotation("ProductVersion", "6.0.3") | |||
| .HasAnnotation("Relational:MaxIdentifierLength", 128); | |||
| SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsuranceCompany", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<string>("City") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Country") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Fax") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("LegalAddress") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("LegalEmail") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Name") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PhoneNumber") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PostalCode") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.ToTable("InsuranceCompanies"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsurancePolicy", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime>("EndDate") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<long>("InsurerId") | |||
| .HasColumnType("bigint"); | |||
| b.Property<decimal>("Premium") | |||
| .HasColumnType("decimal(18,2)"); | |||
| b.Property<DateTime>("StartDate") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Type") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("InsurerId"); | |||
| b.ToTable("InsurancePolicies"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.Insurer", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<string>("Address") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("City") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Country") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime>("DateOfBirth") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Email") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("FirstName") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<long>("InsuranceCompanyId") | |||
| .HasColumnType("bigint"); | |||
| b.Property<string>("LastName") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PhoneNumber") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PostalCode") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("InsuranceCompanyId"); | |||
| b.ToTable("Insurers"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsurancePolicy", b => | |||
| { | |||
| b.HasOne("Diligent.WebAPI.Data.Entities.Insurer", "Insurer") | |||
| .WithMany() | |||
| .HasForeignKey("InsurerId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| b.Navigation("Insurer"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.Insurer", b => | |||
| { | |||
| b.HasOne("Diligent.WebAPI.Data.Entities.InsuranceCompany", "InsuranceCompany") | |||
| .WithMany() | |||
| .HasForeignKey("InsuranceCompanyId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| b.Navigation("InsuranceCompany"); | |||
| }); | |||
| #pragma warning restore 612, 618 | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,115 @@ | |||
| using System; | |||
| using Microsoft.EntityFrameworkCore.Migrations; | |||
| #nullable disable | |||
| namespace Diligent.WebAPI.Data.Migrations | |||
| { | |||
| public partial class Initial : Migration | |||
| { | |||
| protected override void Up(MigrationBuilder migrationBuilder) | |||
| { | |||
| migrationBuilder.CreateTable( | |||
| name: "InsuranceCompanies", | |||
| columns: table => new | |||
| { | |||
| Id = table.Column<long>(type: "bigint", nullable: false) | |||
| .Annotation("SqlServer:Identity", "1, 1"), | |||
| Name = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| PhoneNumber = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| Fax = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| City = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| Country = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| PostalCode = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| LegalAddress = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| LegalEmail = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| CreatedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
| UpdatedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: true), | |||
| DeletedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: true) | |||
| }, | |||
| constraints: table => | |||
| { | |||
| table.PrimaryKey("PK_InsuranceCompanies", x => x.Id); | |||
| }); | |||
| migrationBuilder.CreateTable( | |||
| name: "Insurers", | |||
| columns: table => new | |||
| { | |||
| Id = table.Column<long>(type: "bigint", nullable: false) | |||
| .Annotation("SqlServer:Identity", "1, 1"), | |||
| FirstName = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| LastName = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| DateOfBirth = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
| PhoneNumber = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| City = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| Country = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| PostalCode = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| Address = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| Email = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| InsuranceCompanyId = table.Column<long>(type: "bigint", nullable: false), | |||
| CreatedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
| UpdatedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: true), | |||
| DeletedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: true) | |||
| }, | |||
| constraints: table => | |||
| { | |||
| table.PrimaryKey("PK_Insurers", x => x.Id); | |||
| table.ForeignKey( | |||
| name: "FK_Insurers_InsuranceCompanies_InsuranceCompanyId", | |||
| column: x => x.InsuranceCompanyId, | |||
| principalTable: "InsuranceCompanies", | |||
| principalColumn: "Id", | |||
| onDelete: ReferentialAction.Cascade); | |||
| }); | |||
| migrationBuilder.CreateTable( | |||
| name: "InsurancePolicies", | |||
| columns: table => new | |||
| { | |||
| Id = table.Column<long>(type: "bigint", nullable: false) | |||
| .Annotation("SqlServer:Identity", "1, 1"), | |||
| Premium = table.Column<decimal>(type: "decimal(18,2)", nullable: false), | |||
| StartDate = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
| EndDate = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
| Type = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| InsurerId = table.Column<long>(type: "bigint", nullable: false), | |||
| CreatedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
| UpdatedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: true), | |||
| DeletedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: true) | |||
| }, | |||
| constraints: table => | |||
| { | |||
| table.PrimaryKey("PK_InsurancePolicies", x => x.Id); | |||
| table.ForeignKey( | |||
| name: "FK_InsurancePolicies_Insurers_InsurerId", | |||
| column: x => x.InsurerId, | |||
| principalTable: "Insurers", | |||
| principalColumn: "Id", | |||
| onDelete: ReferentialAction.Cascade); | |||
| }); | |||
| migrationBuilder.CreateIndex( | |||
| name: "IX_InsurancePolicies_InsurerId", | |||
| table: "InsurancePolicies", | |||
| column: "InsurerId"); | |||
| migrationBuilder.CreateIndex( | |||
| name: "IX_Insurers_InsuranceCompanyId", | |||
| table: "Insurers", | |||
| column: "InsuranceCompanyId"); | |||
| } | |||
| protected override void Down(MigrationBuilder migrationBuilder) | |||
| { | |||
| migrationBuilder.DropTable( | |||
| name: "InsurancePolicies"); | |||
| migrationBuilder.DropTable( | |||
| name: "Insurers"); | |||
| migrationBuilder.DropTable( | |||
| name: "InsuranceCompanies"); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,288 @@ | |||
| // <auto-generated /> | |||
| using System; | |||
| using Diligent.WebAPI.Data; | |||
| using Microsoft.EntityFrameworkCore; | |||
| using Microsoft.EntityFrameworkCore.Infrastructure; | |||
| using Microsoft.EntityFrameworkCore.Metadata; | |||
| using Microsoft.EntityFrameworkCore.Migrations; | |||
| using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | |||
| #nullable disable | |||
| namespace Diligent.WebAPI.Data.Migrations | |||
| { | |||
| [DbContext(typeof(DatabaseContext))] | |||
| [Migration("20220815162411_AddedWebhookTables")] | |||
| partial class AddedWebhookTables | |||
| { | |||
| protected override void BuildTargetModel(ModelBuilder modelBuilder) | |||
| { | |||
| #pragma warning disable 612, 618 | |||
| modelBuilder | |||
| .HasAnnotation("ProductVersion", "6.0.3") | |||
| .HasAnnotation("Relational:MaxIdentifierLength", 128); | |||
| SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsuranceCompany", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<string>("City") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Country") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Fax") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("LegalAddress") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("LegalEmail") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Name") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PhoneNumber") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PostalCode") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.ToTable("InsuranceCompanies"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsurancePolicy", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime>("EndDate") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<long>("InsurerId") | |||
| .HasColumnType("bigint"); | |||
| b.Property<decimal>("Premium") | |||
| .HasColumnType("decimal(18,2)"); | |||
| b.Property<DateTime>("StartDate") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Type") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("InsurerId"); | |||
| b.ToTable("InsurancePolicies"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.Insurer", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<string>("Address") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("City") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Country") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime>("DateOfBirth") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Email") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("FirstName") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<long>("InsuranceCompanyId") | |||
| .HasColumnType("bigint"); | |||
| b.Property<string>("LastName") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PhoneNumber") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PostalCode") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("InsuranceCompanyId"); | |||
| b.ToTable("Insurers"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.WebhookDefinition", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Description") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("DisplayName") | |||
| .IsRequired() | |||
| .HasMaxLength(100) | |||
| .HasColumnType("nvarchar(100)"); | |||
| b.Property<string>("Name") | |||
| .IsRequired() | |||
| .HasMaxLength(100) | |||
| .HasColumnType("nvarchar(100)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.ToTable("WebhookDefinitions"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.WebhookSubscription", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<bool>("IsActive") | |||
| .HasColumnType("bit"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<long>("WebhookDefinitionId") | |||
| .HasColumnType("bigint"); | |||
| b.Property<string>("WebhookURL") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("WebhookDefinitionId"); | |||
| b.ToTable("WebhookSubscriptions"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsurancePolicy", b => | |||
| { | |||
| b.HasOne("Diligent.WebAPI.Data.Entities.Insurer", "Insurer") | |||
| .WithMany() | |||
| .HasForeignKey("InsurerId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| b.Navigation("Insurer"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.Insurer", b => | |||
| { | |||
| b.HasOne("Diligent.WebAPI.Data.Entities.InsuranceCompany", "InsuranceCompany") | |||
| .WithMany() | |||
| .HasForeignKey("InsuranceCompanyId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| b.Navigation("InsuranceCompany"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.WebhookSubscription", b => | |||
| { | |||
| b.HasOne("Diligent.WebAPI.Data.Entities.WebhookDefinition", "WebhookDefinition") | |||
| .WithMany() | |||
| .HasForeignKey("WebhookDefinitionId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| b.Navigation("WebhookDefinition"); | |||
| }); | |||
| #pragma warning restore 612, 618 | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,69 @@ | |||
| using System; | |||
| using Microsoft.EntityFrameworkCore.Migrations; | |||
| #nullable disable | |||
| namespace Diligent.WebAPI.Data.Migrations | |||
| { | |||
| public partial class AddedWebhookTables : Migration | |||
| { | |||
| protected override void Up(MigrationBuilder migrationBuilder) | |||
| { | |||
| migrationBuilder.CreateTable( | |||
| name: "WebhookDefinitions", | |||
| columns: table => new | |||
| { | |||
| Id = table.Column<long>(type: "bigint", nullable: false) | |||
| .Annotation("SqlServer:Identity", "1, 1"), | |||
| Name = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), | |||
| DisplayName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), | |||
| Description = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| CreatedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
| UpdatedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: true), | |||
| DeletedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: true) | |||
| }, | |||
| constraints: table => | |||
| { | |||
| table.PrimaryKey("PK_WebhookDefinitions", x => x.Id); | |||
| }); | |||
| migrationBuilder.CreateTable( | |||
| name: "WebhookSubscriptions", | |||
| columns: table => new | |||
| { | |||
| Id = table.Column<long>(type: "bigint", nullable: false) | |||
| .Annotation("SqlServer:Identity", "1, 1"), | |||
| WebhookURL = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
| IsActive = table.Column<bool>(type: "bit", nullable: false), | |||
| WebhookDefinitionId = table.Column<long>(type: "bigint", nullable: false), | |||
| CreatedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
| UpdatedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: true), | |||
| DeletedAtUtc = table.Column<DateTime>(type: "datetime2", nullable: true) | |||
| }, | |||
| constraints: table => | |||
| { | |||
| table.PrimaryKey("PK_WebhookSubscriptions", x => x.Id); | |||
| table.ForeignKey( | |||
| name: "FK_WebhookSubscriptions_WebhookDefinitions_WebhookDefinitionId", | |||
| column: x => x.WebhookDefinitionId, | |||
| principalTable: "WebhookDefinitions", | |||
| principalColumn: "Id", | |||
| onDelete: ReferentialAction.Cascade); | |||
| }); | |||
| migrationBuilder.CreateIndex( | |||
| name: "IX_WebhookSubscriptions_WebhookDefinitionId", | |||
| table: "WebhookSubscriptions", | |||
| column: "WebhookDefinitionId"); | |||
| } | |||
| protected override void Down(MigrationBuilder migrationBuilder) | |||
| { | |||
| migrationBuilder.DropTable( | |||
| name: "WebhookSubscriptions"); | |||
| migrationBuilder.DropTable( | |||
| name: "WebhookDefinitions"); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,286 @@ | |||
| // <auto-generated /> | |||
| using System; | |||
| using Diligent.WebAPI.Data; | |||
| using Microsoft.EntityFrameworkCore; | |||
| using Microsoft.EntityFrameworkCore.Infrastructure; | |||
| using Microsoft.EntityFrameworkCore.Metadata; | |||
| using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | |||
| #nullable disable | |||
| namespace Diligent.WebAPI.Data.Migrations | |||
| { | |||
| [DbContext(typeof(DatabaseContext))] | |||
| partial class DatabaseContextModelSnapshot : ModelSnapshot | |||
| { | |||
| protected override void BuildModel(ModelBuilder modelBuilder) | |||
| { | |||
| #pragma warning disable 612, 618 | |||
| modelBuilder | |||
| .HasAnnotation("ProductVersion", "6.0.3") | |||
| .HasAnnotation("Relational:MaxIdentifierLength", 128); | |||
| SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsuranceCompany", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<string>("City") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Country") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Fax") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("LegalAddress") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("LegalEmail") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Name") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PhoneNumber") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PostalCode") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.ToTable("InsuranceCompanies"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsurancePolicy", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime>("EndDate") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<long>("InsurerId") | |||
| .HasColumnType("bigint"); | |||
| b.Property<decimal>("Premium") | |||
| .HasColumnType("decimal(18,2)"); | |||
| b.Property<DateTime>("StartDate") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Type") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("InsurerId"); | |||
| b.ToTable("InsurancePolicies"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.Insurer", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<string>("Address") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("City") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Country") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime>("DateOfBirth") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Email") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("FirstName") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<long>("InsuranceCompanyId") | |||
| .HasColumnType("bigint"); | |||
| b.Property<string>("LastName") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PhoneNumber") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PostalCode") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("InsuranceCompanyId"); | |||
| b.ToTable("Insurers"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.WebhookDefinition", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("Description") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("DisplayName") | |||
| .IsRequired() | |||
| .HasMaxLength(100) | |||
| .HasColumnType("nvarchar(100)"); | |||
| b.Property<string>("Name") | |||
| .IsRequired() | |||
| .HasMaxLength(100) | |||
| .HasColumnType("nvarchar(100)"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.HasKey("Id"); | |||
| b.ToTable("WebhookDefinitions"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.WebhookSubscription", b => | |||
| { | |||
| b.Property<long>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("bigint"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"), 1L, 1); | |||
| b.Property<DateTime>("CreatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<DateTime?>("DeletedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<bool>("IsActive") | |||
| .HasColumnType("bit"); | |||
| b.Property<DateTime?>("UpdatedAtUtc") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<long>("WebhookDefinitionId") | |||
| .HasColumnType("bigint"); | |||
| b.Property<string>("WebhookURL") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("WebhookDefinitionId"); | |||
| b.ToTable("WebhookSubscriptions"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsurancePolicy", b => | |||
| { | |||
| b.HasOne("Diligent.WebAPI.Data.Entities.Insurer", "Insurer") | |||
| .WithMany() | |||
| .HasForeignKey("InsurerId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| b.Navigation("Insurer"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.Insurer", b => | |||
| { | |||
| b.HasOne("Diligent.WebAPI.Data.Entities.InsuranceCompany", "InsuranceCompany") | |||
| .WithMany() | |||
| .HasForeignKey("InsuranceCompanyId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| b.Navigation("InsuranceCompany"); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.WebhookSubscription", b => | |||
| { | |||
| b.HasOne("Diligent.WebAPI.Data.Entities.WebhookDefinition", "WebhookDefinition") | |||
| .WithMany() | |||
| .HasForeignKey("WebhookDefinitionId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| b.Navigation("WebhookDefinition"); | |||
| }); | |||
| #pragma warning restore 612, 618 | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,5 @@ | |||
| global using Microsoft.EntityFrameworkCore; | |||
| global using Microsoft.Extensions.Configuration; | |||
| global using Microsoft.Extensions.DependencyInjection; | |||
| global using System.ComponentModel.DataAnnotations; | |||
| global using Diligent.WebAPI.Data.Entities; | |||
| @@ -0,0 +1,16 @@ | |||
| namespace Diligent.WebAPI.Host.Attributes | |||
| { | |||
| [AttributeUsage(AttributeTargets.Method)] | |||
| public class AuthorizeAttribute : Attribute, IAuthorizationFilter | |||
| { | |||
| public void OnAuthorization(AuthorizationFilterContext context) | |||
| { | |||
| User? user = (User?)context.HttpContext.Items["User"]; | |||
| if (user == null) | |||
| { | |||
| // not logged in | |||
| context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized }; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| { | |||
| [ApiVersion("1.0")] | |||
| [ApiController] | |||
| [Route("v{version:apiVersion}/insurance-companies")] | |||
| public class InsuranceCompaniesController : ControllerBase | |||
| { | |||
| private readonly IInsuranceCompaniesService _insuranceCompaniesService; | |||
| public InsuranceCompaniesController(IInsuranceCompaniesService insuranceCompaniesService) | |||
| { | |||
| _insuranceCompaniesService = insuranceCompaniesService; | |||
| } | |||
| /// <summary> | |||
| /// Get list of all insurance companies | |||
| /// </summary> | |||
| [HttpGet] | |||
| [ProducesResponseType(typeof(List<InsuranceCompanyViewDto>), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> GetInsuranceCompanies() | |||
| { | |||
| return Ok(await _insuranceCompaniesService.GetInsuranceCompanies()); | |||
| } | |||
| /// <summary> | |||
| /// Get insurance company by id | |||
| /// </summary> | |||
| [HttpGet("{id}")] | |||
| [ProducesResponseType(typeof(InsuranceCompanyViewDto), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> GetInsuranceCompany(long id) | |||
| { | |||
| return Ok(await _insuranceCompaniesService.GetInsuranceCompany(id)); | |||
| } | |||
| /// <summary> | |||
| /// Create insurance company | |||
| /// </summary> | |||
| [HttpPost] | |||
| [ProducesResponseType(typeof(InsuranceCompanyViewDto), StatusCodes.Status201Created)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> CreateInsuranceCompany([FromBody] InsuranceCompanyCreateDto insuranceCompanyCreateDto) | |||
| { | |||
| await _insuranceCompaniesService.CreateInsuranceCompany(insuranceCompanyCreateDto); | |||
| return StatusCode((int)HttpStatusCode.Created); | |||
| } | |||
| /// <summary> | |||
| /// Update insurance company | |||
| /// </summary> | |||
| [HttpPut("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> UpdateInsuranceCompany(long id, [FromBody] InsuranceCompanyUpdateDto insuranceCompanyUpdateDto) | |||
| { | |||
| await _insuranceCompaniesService.UpdateInsuranceCompany(id, insuranceCompanyUpdateDto); | |||
| return Ok(); | |||
| } | |||
| /// <summary> | |||
| /// Delete the specific insurance company | |||
| /// </summary> | |||
| [HttpDelete("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status204NoContent)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> DeleteInsuranceCompany(long id) | |||
| { | |||
| await _insuranceCompaniesService.DeleteInsuranceCompany(id); | |||
| return NoContent(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,79 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| { | |||
| [ApiVersion("1.0")] | |||
| [ApiController] | |||
| [Route("v{version:apiVersion}/insurance-policies")] | |||
| public class InsurancePoliciesController : ControllerBase | |||
| { | |||
| private readonly IInsurancePoliciesService _insurancePoliciesService; | |||
| private readonly IMapper _mapper; | |||
| public InsurancePoliciesController(IInsurancePoliciesService insurancePoliciesService, | |||
| IMapper mapper) | |||
| { | |||
| _insurancePoliciesService = insurancePoliciesService; | |||
| _mapper = mapper; | |||
| } | |||
| /// <summary> | |||
| /// Get list of all insurance policies | |||
| /// </summary> | |||
| [HttpGet] | |||
| [ProducesResponseType(typeof(List<InsurancePolicyViewDto>), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> GetInsurancePolicies() | |||
| { | |||
| return Ok(await _insurancePoliciesService.GetInsurancePolicies()); | |||
| } | |||
| /// <summary> | |||
| /// Get insurance policy by id | |||
| /// </summary> | |||
| [HttpGet("{id}")] | |||
| [ProducesResponseType(typeof(InsurancePolicyViewDto), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<ActionResult<InsurancePolicyViewDto>> GetInsurancePolicy(long id) | |||
| { | |||
| return Ok(await _insurancePoliciesService.GetInsurancePolicy(id)); | |||
| } | |||
| /// <summary> | |||
| /// Create insurance policy | |||
| /// </summary> | |||
| [HttpPost] | |||
| [ProducesResponseType(StatusCodes.Status201Created)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<ActionResult> CreateInsurancePolicy(InsurancePolicyCreateDto InsurancePolicyCreateDto) | |||
| { | |||
| await _insurancePoliciesService.CreateInsurancePolicy(InsurancePolicyCreateDto); | |||
| return StatusCode((int)HttpStatusCode.Created); | |||
| } | |||
| /// <summary> | |||
| /// Update insurance policy | |||
| /// </summary> | |||
| [HttpPut("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<ActionResult> UpdateInsurancePolicy(long id, InsurancePolicyUpdateDto insurancePolicyUpdateDTO) | |||
| { | |||
| await _insurancePoliciesService.UpdateInsurancePolicy(id, insurancePolicyUpdateDTO); | |||
| return Ok(); | |||
| } | |||
| /// <summary> | |||
| /// Delete the specific insurance policy | |||
| /// </summary> | |||
| [HttpDelete("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status204NoContent)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<ActionResult> DeleteInsurancePolicy(long id) | |||
| { | |||
| await _insurancePoliciesService.DeleteInsurancePolicy(id); | |||
| return NoContent(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| { | |||
| [ApiVersion("1.0")] | |||
| [ApiController] | |||
| [Route("v{version:apiVersion}/insurers")] | |||
| public class InsurersController : ControllerBase | |||
| { | |||
| private readonly IInsurersService _insurersService; | |||
| public InsurersController(IInsurersService insurers) | |||
| { | |||
| _insurersService = insurers; | |||
| } | |||
| /// <summary> | |||
| /// Get list of all insusers | |||
| /// </summary> | |||
| [HttpGet] | |||
| [ProducesResponseType(typeof(List<InsurerViewDto>), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> GetInsurers() | |||
| { | |||
| return Ok(await _insurersService.GetInsurers()); | |||
| } | |||
| /// <summary> | |||
| /// Get insurer by id | |||
| /// </summary> | |||
| [HttpGet("{id}")] | |||
| [ProducesResponseType(typeof(InsurerViewDto), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> GetInsurer(long id) | |||
| { | |||
| return Ok(await _insurersService.GetInsurer(id)); | |||
| } | |||
| /// <summary> | |||
| /// Create insurer | |||
| /// </summary> | |||
| [HttpPost] | |||
| [ProducesResponseType(StatusCodes.Status201Created)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> CreateInsurer([FromBody] InsurerCreateDto insurerCreateDto) | |||
| { | |||
| await _insurersService.CreateInsurer(insurerCreateDto); | |||
| return StatusCode((int)HttpStatusCode.Created); | |||
| } | |||
| /// <summary> | |||
| /// Update insurer | |||
| /// </summary> | |||
| [HttpPut("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> UpdateInsurer(long id, [FromBody] InsurerUpdateDto insurerUpdateDto) | |||
| { | |||
| await _insurersService.UpdateInsurer(id, insurerUpdateDto); | |||
| return Ok(); | |||
| } | |||
| /// <summary> | |||
| /// Delete insurer | |||
| /// </summary> | |||
| [HttpDelete("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status204NoContent)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> DeleteInsurer(long insurerId) | |||
| { | |||
| await _insurersService.DeleteInsurerAsync(insurerId); | |||
| return NoContent(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| { | |||
| [ApiVersion("1.0")] | |||
| [Route("v{version:apiVersion}/users")] | |||
| [ApiController] | |||
| public class UsersController : ControllerBase | |||
| { | |||
| private readonly IUserService _userService; | |||
| public UsersController(IUserService userService) | |||
| { | |||
| _userService = userService; | |||
| } | |||
| [Authorize] | |||
| [HttpGet] | |||
| public IActionResult GetAll() | |||
| { | |||
| return Ok("Hello from protected route"); | |||
| } | |||
| [HttpPost("authenticate")] | |||
| public IActionResult Authenticate([FromBody] AuthenticateRequestDto model) | |||
| { | |||
| var response = _userService.Authenticate(model); | |||
| if (response == null) | |||
| return BadRequest(new { message = "Username or password is incorrect" }); | |||
| return Ok(response); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,42 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| { | |||
| [ApiVersion("1.0")] | |||
| [ApiController] | |||
| [Route("v{version:apiVersion}/webhooks")] | |||
| public class WebhooksController : ControllerBase | |||
| { | |||
| private readonly IWebhookSubscriptionService _webhookSubscriptionService; | |||
| private readonly IWebhookDefinitionService _webhookDefinitionService; | |||
| public WebhooksController( | |||
| IWebhookSubscriptionService subscriptionService, | |||
| IWebhookDefinitionService definitionsService) | |||
| { | |||
| _webhookSubscriptionService = subscriptionService; | |||
| _webhookDefinitionService = definitionsService; | |||
| } | |||
| /// <summary> | |||
| /// Create webhook subscription | |||
| /// </summary> | |||
| [HttpPost] | |||
| [ProducesResponseType(StatusCodes.Status201Created)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> Post([FromBody] WebhookSubscriptionCreateDto dto) | |||
| { | |||
| await _webhookSubscriptionService.CreateWebhookSubscription(dto); | |||
| return StatusCode(StatusCodes.Status201Created); | |||
| } | |||
| /// <summary> | |||
| /// Get all webhook definitions | |||
| /// </summary> | |||
| [HttpGet("definitions")] | |||
| [ProducesResponseType(typeof(List<WebhookDefinitionViewDto>), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> GetDefinitions() | |||
| { | |||
| return Ok(await _webhookDefinitionService.GetAll()); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V2 | |||
| { | |||
| [ApiVersion("2.0")] | |||
| [ApiController] | |||
| [Route("v{version:apiVersion}/insurance-companies")] | |||
| public class InsuranceCompaniesController : ControllerBase | |||
| { | |||
| private readonly IInsuranceCompaniesService insuranceCompaniesService; | |||
| public InsuranceCompaniesController(IInsuranceCompaniesService insuranceCompaniesService) | |||
| { | |||
| this.insuranceCompaniesService = insuranceCompaniesService; | |||
| } | |||
| /// <summary> | |||
| /// Get list of all insurance companies | |||
| /// </summary> | |||
| [HttpGet] | |||
| [ProducesResponseType(typeof(List<InsuranceCompanyViewDto>), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> GetInsuranceCompanies() | |||
| { | |||
| return Ok(await insuranceCompaniesService.GetInsuranceCompanies()); | |||
| } | |||
| /// <summary> | |||
| /// Get insurance company by id | |||
| /// </summary> | |||
| [HttpGet("{id}")] | |||
| [ProducesResponseType(typeof(InsuranceCompanyViewDto), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> GetInsuranceCompany(long id) | |||
| { | |||
| return Ok(await insuranceCompaniesService.GetInsuranceCompany(id)); | |||
| } | |||
| /// <summary> | |||
| /// Create insurance company | |||
| /// </summary> | |||
| [HttpPost] | |||
| [ProducesResponseType(typeof(InsuranceCompanyViewDto), StatusCodes.Status201Created)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> CreateInsuranceCompany([FromBody] InsuranceCompanyCreateDto insuranceCompanyCreateDto) | |||
| { | |||
| await insuranceCompaniesService.CreateInsuranceCompany(insuranceCompanyCreateDto); | |||
| return StatusCode((int)HttpStatusCode.Created); | |||
| } | |||
| /// <summary> | |||
| /// Update insurance company | |||
| /// </summary> | |||
| [HttpPut("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> UpdateInsuranceCompany(long id, [FromBody] InsuranceCompanyUpdateDto insuranceCompanyUpdateDto) | |||
| { | |||
| await insuranceCompaniesService.UpdateInsuranceCompany(id, insuranceCompanyUpdateDto); | |||
| return Ok(); | |||
| } | |||
| /// <summary> | |||
| /// Delete the specific insurance company | |||
| /// </summary> | |||
| [HttpDelete("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status204NoContent)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> DeleteInsuranceCompany(long id) | |||
| { | |||
| await insuranceCompaniesService.DeleteInsuranceCompany(id); | |||
| return NoContent(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,79 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V2 | |||
| { | |||
| [ApiVersion("2.0")] | |||
| [ApiController] | |||
| [Route("v{version:apiVersion}/insurance-policies")] | |||
| public class InsurancePoliciesController : ControllerBase | |||
| { | |||
| private readonly IInsurancePoliciesService _insurancePoliciesService; | |||
| private readonly IMapper _mapper; | |||
| public InsurancePoliciesController(IInsurancePoliciesService insurancePoliciesService, | |||
| IMapper mapper) | |||
| { | |||
| _insurancePoliciesService = insurancePoliciesService; | |||
| _mapper = mapper; | |||
| } | |||
| /// <summary> | |||
| /// Get list of all insurance policies | |||
| /// </summary> | |||
| [HttpGet] | |||
| [ProducesResponseType(typeof(List<InsurancePolicyViewDto>), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> GetInsurancePolicies() | |||
| { | |||
| return Ok(await _insurancePoliciesService.GetInsurancePolicies()); | |||
| } | |||
| /// <summary> | |||
| /// Get insurance policy by id | |||
| /// </summary> | |||
| [HttpGet("{id}")] | |||
| [ProducesResponseType(typeof(InsurancePolicyViewDto), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<ActionResult<InsurancePolicyViewDto>> GetInsurancePolicy(long id) | |||
| { | |||
| return Ok(await _insurancePoliciesService.GetInsurancePolicy(id)); | |||
| } | |||
| /// <summary> | |||
| /// Create insurance policy | |||
| /// </summary> | |||
| [HttpPost] | |||
| [ProducesResponseType(StatusCodes.Status201Created)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<ActionResult> CreateInsurancePolicy(InsurancePolicyCreateDto InsurancePolicyCreateDto) | |||
| { | |||
| await _insurancePoliciesService.CreateInsurancePolicy(InsurancePolicyCreateDto); | |||
| return StatusCode((int)HttpStatusCode.Created); | |||
| } | |||
| /// <summary> | |||
| /// Update insurance policy | |||
| /// </summary> | |||
| [HttpPut("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<ActionResult> UpdateInsurancePolicy(long id, InsurancePolicyUpdateDto insurancePolicyUpdateDTO) | |||
| { | |||
| await _insurancePoliciesService.UpdateInsurancePolicy(id, insurancePolicyUpdateDTO); | |||
| return Ok(); | |||
| } | |||
| /// <summary> | |||
| /// Delete the specific insurance policy | |||
| /// </summary> | |||
| [HttpDelete("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status204NoContent)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<ActionResult> DeleteInsurancePolicy(long id) | |||
| { | |||
| await _insurancePoliciesService.DeleteInsurancePolicy(id); | |||
| return NoContent(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V2 | |||
| { | |||
| [ApiVersion("2.0")] | |||
| [ApiController] | |||
| [Route("v{version:apiVersion}/insurers")] | |||
| public class InsurersController : ControllerBase | |||
| { | |||
| private readonly IInsurersService _insurersService; | |||
| public InsurersController(IInsurersService insurers) | |||
| { | |||
| _insurersService = insurers; | |||
| } | |||
| /// <summary> | |||
| /// Get list of all insusers | |||
| /// </summary> | |||
| [HttpGet] | |||
| [ProducesResponseType(typeof(List<InsurerViewDto>), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> GetInsurers() | |||
| { | |||
| return Ok(await _insurersService.GetInsurers()); | |||
| } | |||
| /// <summary> | |||
| /// Get insurer by id | |||
| /// </summary> | |||
| [HttpGet("{id}")] | |||
| [ProducesResponseType(typeof(InsurerViewDto), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> GetInsurer(long id) | |||
| { | |||
| return Ok(await _insurersService.GetInsurer(id)); | |||
| } | |||
| /// <summary> | |||
| /// Create insurer | |||
| /// </summary> | |||
| [HttpPost] | |||
| [ProducesResponseType(StatusCodes.Status201Created)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> CreateInsurer([FromBody] InsurerCreateDto insurerCreateDto) | |||
| { | |||
| await _insurersService.CreateInsurer(insurerCreateDto); | |||
| return StatusCode((int)HttpStatusCode.Created); | |||
| } | |||
| /// <summary> | |||
| /// Update insurer | |||
| /// </summary> | |||
| [HttpPut("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> UpdateInsurer(long id, [FromBody] InsurerUpdateDto insurerUpdateDto) | |||
| { | |||
| await _insurersService.UpdateInsurer(id, insurerUpdateDto); | |||
| return Ok(); | |||
| } | |||
| /// <summary> | |||
| /// Delete insurer | |||
| /// </summary> | |||
| [HttpDelete("{id}")] | |||
| [ProducesResponseType(StatusCodes.Status204NoContent)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| [ProducesResponseType(StatusCodes.Status404NotFound)] | |||
| public async Task<IActionResult> DeleteInsurer(long insurerId) | |||
| { | |||
| await _insurersService.DeleteInsurerAsync(insurerId); | |||
| return NoContent(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V2 | |||
| { | |||
| [ApiVersion("2.0")] | |||
| [Route("v{version:apiVersion}/[controller]")] | |||
| [ApiController] | |||
| public class UsersController : ControllerBase | |||
| { | |||
| private readonly IUserService _userService; | |||
| public UsersController(IUserService userService) | |||
| { | |||
| _userService = userService; | |||
| } | |||
| [Authorize] | |||
| [HttpGet] | |||
| public IActionResult GetAll() | |||
| { | |||
| return Ok("Hello from protected route"); | |||
| } | |||
| [HttpPost("authenticate")] | |||
| public IActionResult Authenticate([FromBody] AuthenticateRequestDto model) | |||
| { | |||
| var response = _userService.Authenticate(model); | |||
| if (response == null) | |||
| return BadRequest(new { message = "Username or password is incorrect" }); | |||
| return Ok(response); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,42 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V2 | |||
| { | |||
| [ApiVersion("2.0")] | |||
| [ApiController] | |||
| [Route("v{version:apiVersion}/webhooks")] | |||
| public class WebhooksController : ControllerBase | |||
| { | |||
| private readonly IWebhookSubscriptionService _webhookSubscriptionService; | |||
| private readonly IWebhookDefinitionService _webhookDefinitionService; | |||
| public WebhooksController( | |||
| IWebhookSubscriptionService subscriptionService, | |||
| IWebhookDefinitionService definitionsService) | |||
| { | |||
| _webhookSubscriptionService = subscriptionService; | |||
| _webhookDefinitionService = definitionsService; | |||
| } | |||
| /// <summary> | |||
| /// Create webhook subscription | |||
| /// </summary> | |||
| [HttpPost] | |||
| [ProducesResponseType(StatusCodes.Status201Created)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> Post([FromBody] WebhookSubscriptionCreateDto dto) | |||
| { | |||
| await _webhookSubscriptionService.CreateWebhookSubscription(dto); | |||
| return StatusCode(StatusCodes.Status201Created); | |||
| } | |||
| /// <summary> | |||
| /// Get all webhook definitions | |||
| /// </summary> | |||
| [HttpGet("definitions")] | |||
| [ProducesResponseType(typeof(List<WebhookDefinitionViewDto>), StatusCodes.Status200OK)] | |||
| [ProducesResponseType(typeof(ErrorResponseDto), StatusCodes.Status400BadRequest)] | |||
| public async Task<IActionResult> GetDefinitions() | |||
| { | |||
| return Ok(await _webhookDefinitionService.GetAll()); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,42 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk.Web"> | |||
| <PropertyGroup> | |||
| <TargetFramework>net6.0</TargetFramework> | |||
| <Nullable>enable</Nullable> | |||
| <ImplicitUsings>enable</ImplicitUsings> | |||
| </PropertyGroup> | |||
| <PropertyGroup> | |||
| <GenerateDocumentationFile>true</GenerateDocumentationFile> | |||
| </PropertyGroup> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | |||
| <NoWarn>1701;1702;1591</NoWarn> | |||
| </PropertyGroup> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||
| <NoWarn>1701;1702;1591</NoWarn> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <None Include="..\.editorconfig" Link=".editorconfig" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" /> | |||
| <PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.2.9" /> | |||
| <PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" /> | |||
| <PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" /> | |||
| <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.3"> | |||
| <PrivateAssets>all</PrivateAssets> | |||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | |||
| </PackageReference> | |||
| <PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.2" /> | |||
| <PackageReference Include="Serilog.AspNetCore" Version="5.0.0" /> | |||
| <PackageReference Include="Serilog.Sinks.Seq" Version="5.1.1" /> | |||
| <PackageReference Include="SerilogTimings" Version="2.3.0" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\Diligent.WebAPI.Business\Diligent.WebAPI.Business.csproj" /> | |||
| <ProjectReference Include="..\Diligent.WebAPI.Contracts\Diligent.WebAPI.Contracts.csproj" /> | |||
| <ProjectReference Include="..\Diligent.WebAPI.Data\Diligent.WebAPI.Data.csproj" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,11 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
| <PropertyGroup> | |||
| <Controller_SelectedScaffolderID>ApiControllerWithActionsScaffolder</Controller_SelectedScaffolderID> | |||
| <Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath> | |||
| <ActiveDebugProfile>IIS Express</ActiveDebugProfile> | |||
| </PropertyGroup> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | |||
| <DebuggerFlavor>ProjectDebugger</DebuggerFlavor> | |||
| </PropertyGroup> | |||
| </Project> | |||
| @@ -0,0 +1,11 @@ | |||
| namespace Diligent.WebAPI.Host.Extensions | |||
| { | |||
| public static class AuthConfigurationExtension | |||
| { | |||
| public static void ConfigureAuth(this WebApplicationBuilder builder) | |||
| { | |||
| builder.Services.Configure<AuthorizationSettings>(builder.Configuration.GetSection("Authorization")); | |||
| builder.Services.AddScoped<IUserService, UserService>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,31 @@ | |||
| namespace Diligent.WebAPI.Host.Extensions | |||
| { | |||
| public static class BusinessConfigurationExtension | |||
| { | |||
| /// <summary> | |||
| /// Services configuration | |||
| /// </summary> | |||
| public static void ConfigureBusiness(this WebApplicationBuilder builder) | |||
| { | |||
| IServiceCollection services = builder.Services; | |||
| services.AddAutoMapper(typeof(CompanyMappingProfile)); | |||
| services.AddAutoMapper(typeof(WebhookMappingProfile)); | |||
| services.AddAutoMapper(typeof(InsurerMappingProfile)); | |||
| services.AddScoped<IInsurersService, InsurersService>(); | |||
| services.AddScoped<IInsuranceCompaniesService, InsuranceCompaniesService>(); | |||
| services.AddScoped<IInsurancePoliciesService, InsurancePoliciesService>(); | |||
| services.AddScoped<IWebhookSubscriptionService, WebhookSubscriptionService>(); | |||
| services.AddScoped<IWebhookDefinitionService, WebhookDefinitionService>(); | |||
| services.AddScoped<IWebhookPublisherService, WebhookPublisherService>(); | |||
| } | |||
| /// <summary> | |||
| /// App configuration | |||
| /// </summary> | |||
| public static void ConfigureBusiness(this WebApplication app) | |||
| { | |||
| // | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| namespace Diligent.WebAPI.Host.Extensions | |||
| { | |||
| public static class CorrelationIdExtension | |||
| { | |||
| public static IApplicationBuilder UseCorrelationId(this IApplicationBuilder app) | |||
| { | |||
| return app.UseMiddleware<CorrelationMiddleware>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| namespace Diligent.WebAPI.Host.Extensions; | |||
| public static class DataConfigurationExtension | |||
| { | |||
| /// <summary> | |||
| /// Services configuration | |||
| /// </summary> | |||
| public static void ConfigureData(this WebApplicationBuilder builder) | |||
| { | |||
| IServiceCollection services = builder.Services; | |||
| services.ConfigureData(builder.Configuration); | |||
| } | |||
| /// <summary> | |||
| /// App configuration | |||
| /// </summary> | |||
| public static void ConfigureData(this WebApplication app) | |||
| { | |||
| // | |||
| } | |||
| } | |||
| @@ -0,0 +1,36 @@ | |||
| namespace Diligent.WebAPI.Host.Extensions | |||
| { | |||
| public static class HostConfigurationExtension | |||
| { | |||
| /// <summary> | |||
| /// Services configuration | |||
| /// </summary> | |||
| public static void ConfigureHost(this WebApplicationBuilder builder) | |||
| { | |||
| builder.ConfigureAuth(); | |||
| builder.ConfigureValidationMiddleware(); | |||
| builder.ConfigureSwagger(); | |||
| IServiceCollection services = builder.Services; | |||
| services.AddControllers(); | |||
| services.AddEndpointsApiExplorer(); | |||
| } | |||
| /// <summary> | |||
| /// App configuration | |||
| /// </summary> | |||
| public static void ConfigureHost(this WebApplication app) | |||
| { | |||
| app.UseCorrelationId(); | |||
| app.MapControllers(); | |||
| app.SetupData(); | |||
| // custom jwt auth middleware | |||
| app.UseMiddleware<JwtMiddleware>(); | |||
| app.UseDiligExceptionHandler(); | |||
| app.ConfigureSwagger(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| namespace Diligent.WebAPI.Host.Extensions | |||
| { | |||
| public static class ModelValidationMIddlewareExtension | |||
| { | |||
| public static void ConfigureValidationMiddleware(this WebApplicationBuilder builder) | |||
| { | |||
| var services = builder.Services; | |||
| // Override default model validation middleware. | |||
| services.Configure<ApiBehaviorOptions>(options => | |||
| { | |||
| options.SuppressModelStateInvalidFilter = true; | |||
| }); | |||
| // Register custom validation middleware | |||
| services.AddMvcCore(options => | |||
| { | |||
| options.Filters.Add(typeof(ModelValidationMiddleware)); | |||
| }) | |||
| .AddDataAnnotations(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,45 @@ | |||
| namespace Diligent.WebAPI.Host.Extensions | |||
| { | |||
| public static class SwaggerConfigurationExtension | |||
| { | |||
| public static void ConfigureSwagger(this WebApplicationBuilder builder) | |||
| { | |||
| IServiceCollection services = builder.Services; | |||
| services.AddVersionedApiExplorer(setup => | |||
| { | |||
| setup.GroupNameFormat = "'v'VVV"; | |||
| setup.SubstituteApiVersionInUrl = true; | |||
| }); | |||
| services.AddSwaggerGen(options => | |||
| { | |||
| var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; | |||
| options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); | |||
| } | |||
| ); | |||
| services.ConfigureOptions<SwaggerConfigureOptions>(); | |||
| services.AddApiVersioning(options => | |||
| { | |||
| options.AssumeDefaultVersionWhenUnspecified = true; | |||
| options.ReportApiVersions = true; | |||
| options.DefaultApiVersion = new ApiVersion(1, 0); | |||
| options.ApiVersionReader = new UrlSegmentApiVersionReader(); | |||
| }); | |||
| } | |||
| public static void ConfigureSwagger(this WebApplication app) | |||
| { | |||
| if (app.Environment.IsDevelopment()) | |||
| { | |||
| app.UseSwagger(); | |||
| app.UseSwaggerUI(options => | |||
| { | |||
| options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1"); | |||
| options.SwaggerEndpoint("/swagger/v2/swagger.json", "v2"); | |||
| options.RoutePrefix = string.Empty; | |||
| }); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| namespace Diligent.WebAPI.Host.Extensions; | |||
| public static class WebAppExtension | |||
| { | |||
| public static void SetupData(this WebApplication app) | |||
| { | |||
| IServiceScope serviceScope = app.Services.CreateScope(); | |||
| serviceScope.SetupData(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| namespace Diligent.WebAPI.Host.Middlewares | |||
| { | |||
| public class CorrelationMiddleware | |||
| { | |||
| private const string DefaultHeader = "X-Correlation-ID"; | |||
| private readonly RequestDelegate next; | |||
| private readonly ILogger<CorrelationMiddleware> logger; | |||
| public CorrelationMiddleware(RequestDelegate next, ILogger<CorrelationMiddleware> logger) => (this.next,this.logger) = (next,logger); | |||
| public async Task Invoke(HttpContext context) | |||
| { | |||
| if (!context.Request.Headers.TryGetValue(DefaultHeader, out var correlation)) | |||
| { | |||
| correlation = Guid.NewGuid().ToString(); | |||
| } | |||
| context.Response.OnStarting(() => | |||
| { | |||
| if (!context.Response.Headers.ContainsKey(DefaultHeader)) | |||
| { | |||
| context.Response.Headers.Add(DefaultHeader, correlation); | |||
| } | |||
| return Task.CompletedTask; | |||
| }); | |||
| using (logger.BeginScope(new Dictionary<string, object> | |||
| { | |||
| ["CorrelationId"] = correlation | |||
| })) | |||
| { | |||
| context.Items.Add(DefaultHeader, correlation); | |||
| await next(context); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,122 @@ | |||
| using Diligent.WebAPI.Contracts.Exceptions; | |||
| using Diligent.WebAPI.Contracts.Models; | |||
| using Microsoft.AspNetCore.Mvc; | |||
| using Microsoft.Extensions.Options; | |||
| using Newtonsoft.Json; | |||
| using Newtonsoft.Json.Serialization; | |||
| using System.Diagnostics; | |||
| using System.Net; | |||
| using System.Runtime.Serialization; | |||
| namespace Diligent.WebAPI.Host.Middlewares | |||
| { | |||
| public class DiligBadRequestException : Exception | |||
| { | |||
| public const string ExceptionMessage = "Bad request from custom middleware"; | |||
| public const string ExceptionCode = "DiligBadRequestException"; | |||
| public const HttpStatusCode HttpResponseCode = HttpStatusCode.BadRequest; | |||
| public DiligBadRequestException() : base(ExceptionMessage) { } | |||
| public DiligBadRequestException(string message) : base(message) { } | |||
| public DiligBadRequestException(string message, Exception innerException) : base(message, innerException) { } | |||
| public DiligBadRequestException(SerializationInfo info, StreamingContext context) : base(info, context) { } | |||
| } | |||
| public class DiligExceptionMiddleware | |||
| { | |||
| private readonly RequestDelegate _next; | |||
| private readonly ILogger<DiligExceptionMiddleware> _logger; | |||
| private readonly IWebHostEnvironment _env; | |||
| private readonly ApiBehaviorOptions _options; | |||
| public DiligExceptionMiddleware(RequestDelegate next, ILogger<DiligExceptionMiddleware> logger, IWebHostEnvironment env, IOptions<ApiBehaviorOptions> options) | |||
| => (_next, _logger, _env, _options) = (next, logger, env, options.Value); | |||
| public async Task InvokeAsync(HttpContext httpContext) | |||
| { | |||
| try | |||
| { | |||
| await _next(httpContext); | |||
| } | |||
| // Some custom Exceptions | |||
| catch (EntityNotFoundException ex) | |||
| { | |||
| _logger.LogError(ex, DiligBadRequestException.ExceptionMessage); | |||
| await HandleExceptionAsync(httpContext, ex, DiligBadRequestException.ExceptionMessage, HttpStatusCode.NotFound); | |||
| } | |||
| catch (Exception ex) | |||
| { | |||
| // Better solution is to use switch statement | |||
| if(HasInternalExceptionOfType<DiligBadRequestException>(ex)) | |||
| { | |||
| _logger.LogError(ex, DiligBadRequestException.ExceptionMessage); | |||
| await HandleExceptionAsync(httpContext, ex, DiligBadRequestException.ExceptionMessage, DiligBadRequestException.HttpResponseCode); | |||
| } | |||
| else | |||
| { | |||
| await HandleSomethingWentWrongAsync(httpContext, ex); | |||
| } | |||
| } | |||
| } | |||
| private async Task HandleSomethingWentWrongAsync(HttpContext httpContext, Exception ex) | |||
| { | |||
| _logger.LogError(ex, "Something went wrong"); | |||
| await HandleExceptionAsync(httpContext, ex); | |||
| } | |||
| private bool HasInternalExceptionOfType<T>(Exception e) | |||
| { | |||
| if(e.InnerException != null) | |||
| { | |||
| return e is T || HasInternalExceptionOfType<T>(e.InnerException); | |||
| } | |||
| return e is T; | |||
| } | |||
| private Task HandleExceptionAsync(HttpContext context, Exception exception, string? message = null, HttpStatusCode? responseCode = null) | |||
| { | |||
| context.Response.ContentType = "application/json"; | |||
| context.Response.StatusCode = (int)(responseCode ?? HttpStatusCode.InternalServerError); | |||
| string type = null; | |||
| if (_options.ClientErrorMapping.TryGetValue(context.Response.StatusCode, out var clientErrorData)) | |||
| { | |||
| type = clientErrorData.Link; | |||
| } | |||
| var errorTitle = message ?? (_env.IsDevelopment() ? exception.Message : "Internal server error"); | |||
| var errorMessage = _env.IsDevelopment() ? exception.StackTrace : "Something went wrong" ; | |||
| var serializerSettings = new JsonSerializerSettings | |||
| { | |||
| ContractResolver = new CamelCasePropertyNamesContractResolver() | |||
| }; | |||
| var resultError = new ResultError(errorTitle); | |||
| var httpResultError = new HttpResultError() | |||
| { | |||
| ErrorMessage = errorMessage, | |||
| ErrorCode = responseCode ?? HttpStatusCode.InternalServerError | |||
| }; | |||
| resultError.AddCustomError(httpResultError); | |||
| var responseString = JsonConvert.SerializeObject( | |||
| new BaseResult<Exception> | |||
| { | |||
| // Type = type, | |||
| // TraceId = Activity.Current?.Id ?? context?.TraceIdentifier, | |||
| IsSuccess = false, | |||
| Errors = { resultError } | |||
| }, serializerSettings); | |||
| return context.Response.WriteAsync(responseString); | |||
| } | |||
| } | |||
| public static class DiligExceptionMiddlewareExtensions | |||
| { | |||
| public static IApplicationBuilder UseDiligExceptionHandler(this IApplicationBuilder app) | |||
| { | |||
| return app.UseMiddleware<DiligExceptionMiddleware>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,53 @@ | |||
| namespace Diligent.WebAPI.Host.Middlewares | |||
| { | |||
| public class JwtMiddleware | |||
| { | |||
| private readonly RequestDelegate _next; | |||
| private readonly AuthorizationSettings _authSettings; | |||
| public JwtMiddleware(RequestDelegate next, IOptions<AuthorizationSettings> authSettings) | |||
| { | |||
| _next = next; | |||
| _authSettings = authSettings.Value; | |||
| } | |||
| public async Task Invoke(HttpContext context, IUserService userService) | |||
| { | |||
| var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last(); | |||
| if (token != null) | |||
| AttachUserToContext(context, userService, token); | |||
| await _next(context); | |||
| } | |||
| private void AttachUserToContext(HttpContext context, IUserService userService, string token) | |||
| { | |||
| try | |||
| { | |||
| var tokenHandler = new JwtSecurityTokenHandler(); | |||
| var key = Encoding.ASCII.GetBytes(_authSettings.Secret); | |||
| tokenHandler.ValidateToken(token, new TokenValidationParameters | |||
| { | |||
| ValidateIssuerSigningKey = true, | |||
| IssuerSigningKey = new SymmetricSecurityKey(key), | |||
| ValidateIssuer = false, | |||
| ValidateAudience = false, | |||
| // set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later) | |||
| ClockSkew = TimeSpan.Zero | |||
| }, out SecurityToken validatedToken); | |||
| var jwtToken = (JwtSecurityToken)validatedToken; | |||
| var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value); | |||
| // attach user to context on successful jwt validation | |||
| context.Items["User"] = userService.GetById(userId); | |||
| } | |||
| catch | |||
| { | |||
| // do nothing if jwt validation fails | |||
| // user is not attached to context so request won't have access to secure routes | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,29 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Error; | |||
| using Microsoft.AspNetCore.Mvc; | |||
| using Microsoft.AspNetCore.Mvc.Filters; | |||
| namespace Diligent.WebAPI.Host.Middlewares | |||
| { | |||
| public class ModelValidationMiddleware : IActionFilter | |||
| { | |||
| public void OnActionExecuted(ActionExecutedContext context) { } | |||
| public void OnActionExecuting(ActionExecutingContext context) | |||
| { | |||
| if (!context.ModelState.IsValid) | |||
| { | |||
| // create response model | |||
| var response = new ErrorResponseDto("Invalid model") | |||
| { | |||
| // get model validation errors from ModelState | |||
| ValidationItems = context.ModelState | |||
| .Where(x => x.Value != null && x.Value.Errors.Count > 0) | |||
| .Select(x => new ValidationItemDto { Key = x.Key, Value = x.Value?.Errors.Select(e => e.ErrorMessage).First() }) | |||
| .ToList() | |||
| }; | |||
| // return validation model | |||
| context.Result = new BadRequestObjectResult(response); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| namespace Diligent.WebAPI.Host.Options | |||
| { | |||
| public class SwaggerConfigureOptions : IConfigureOptions<SwaggerGenOptions> | |||
| { | |||
| private readonly IApiVersionDescriptionProvider _provider; | |||
| public SwaggerConfigureOptions(IApiVersionDescriptionProvider provider) => _provider = provider; | |||
| public void Configure(SwaggerGenOptions options) | |||
| { | |||
| // add swagger document for every API version discovered | |||
| foreach (var description in _provider.ApiVersionDescriptions) | |||
| { | |||
| options.SwaggerDoc( | |||
| description.GroupName, | |||
| CreateVersionInfo(description)); | |||
| } | |||
| } | |||
| public void Configure(string name, SwaggerGenOptions options) | |||
| { | |||
| Configure(options); | |||
| } | |||
| private OpenApiInfo CreateVersionInfo( | |||
| ApiVersionDescription description) | |||
| { | |||
| var info = new OpenApiInfo() | |||
| { | |||
| Title = "Diligent Web API", | |||
| Version = description.ApiVersion.ToString() | |||
| }; | |||
| if (description.IsDeprecated) | |||
| { | |||
| info.Description += " This API version has been deprecated."; | |||
| } | |||
| return info; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,12 @@ | |||
| var builder = WebApplication.CreateBuilder(args); | |||
| builder.ConfigureHost(); | |||
| builder.ConfigureData(); | |||
| builder.ConfigureBusiness(); | |||
| var app = builder.Build(); | |||
| app.ConfigureHost(); | |||
| app.ConfigureData(); | |||
| app.ConfigureBusiness(); | |||
| app.Run(); | |||
| @@ -0,0 +1,29 @@ | |||
| { | |||
| "$schema": "https://json.schemastore.org/launchsettings.json", | |||
| "iisSettings": { | |||
| "windowsAuthentication": false, | |||
| "anonymousAuthentication": true, | |||
| "iisExpress": { | |||
| "applicationUrl": "http://localhost:26081", | |||
| "sslPort": 0 | |||
| } | |||
| }, | |||
| "profiles": { | |||
| "Diligent.WebAPI.Host": { | |||
| "commandName": "Project", | |||
| "environmentVariables": { | |||
| "ASPNETCORE_ENVIRONMENT": "Development" | |||
| }, | |||
| "applicationUrl": "http://localhost:5116", | |||
| "dotnetRunMessages": true | |||
| }, | |||
| "IIS Express": { | |||
| "commandName": "IISExpress", | |||
| "launchBrowser": true, | |||
| "launchUrl": "", | |||
| "environmentVariables": { | |||
| "ASPNETCORE_ENVIRONMENT": "Development" | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,35 @@ | |||
| global using Diligent.WebAPI.Host.Extensions; | |||
| global using Diligent.WebAPI.Host.Middlewares; | |||
| global using Diligent.WebAPI.Host.Options; | |||
| global using Diligent.WebAPI.Host.Attributes; | |||
| global using Diligent.WebAPI.Data.Extensions; | |||
| global using Diligent.WebAPI.Data.Entities; | |||
| global using Diligent.WebAPI.Business.Settings; | |||
| global using Diligent.WebAPI.Business.Services; | |||
| global using Diligent.WebAPI.Business.Services.Interfaces; | |||
| global using Diligent.WebAPI.Business.MappingProfiles; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Error; | |||
| global using Diligent.WebAPI.Contracts.DTOs.InsuranceCompany; | |||
| global using Diligent.WebAPI.Contracts.DTOs.InsurancePolicy; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Insurer; | |||
| global using Diligent.WebAPI.Contracts.DTOs.WebhookSubscription; | |||
| global using Diligent.WebAPI.Contracts.DTOs.WebhookDefinition; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Auth; | |||
| global using Microsoft.AspNetCore.Mvc; | |||
| global using Microsoft.AspNetCore.Mvc.Versioning; | |||
| global using Microsoft.AspNetCore.Mvc.ApiExplorer; | |||
| global using Microsoft.Extensions.Options; | |||
| global using Microsoft.OpenApi.Models; | |||
| global using Microsoft.AspNetCore.Mvc.Filters; | |||
| global using Microsoft.IdentityModel.Tokens; | |||
| global using System.Reflection; | |||
| global using System.Net; | |||
| global using System.Text; | |||
| global using System.IdentityModel.Tokens.Jwt; | |||
| global using AutoMapper; | |||
| global using Swashbuckle.AspNetCore.SwaggerGen; | |||
| @@ -0,0 +1,8 @@ | |||
| { | |||
| "ConnectionStrings": { | |||
| "WebApi": "Data Source=localhost,2433;User=sa;Password=developer_pw;Initial Catalog=WebApiDB;MultipleActiveResultSets=True" | |||
| }, | |||
| "Authorization": { | |||
| "Secret": "SECRET_ASKGFH#$_#((Y)#I%EWJGDSJTGKEOS@$SAF" | |||
| } | |||
| } | |||
| @@ -0,0 +1,2 @@ | |||
| { | |||
| } | |||
| @@ -0,0 +1,4 @@ | |||
| // <autogenerated /> | |||
| using System; | |||
| using System.Reflection; | |||
| [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] | |||
| @@ -0,0 +1,23 @@ | |||
| //------------------------------------------------------------------------------ | |||
| // <auto-generated> | |||
| // This code was generated by a tool. | |||
| // Runtime Version:4.0.30319.42000 | |||
| // | |||
| // Changes to this file may cause incorrect behavior and will be lost if | |||
| // the code is regenerated. | |||
| // </auto-generated> | |||
| //------------------------------------------------------------------------------ | |||
| using System; | |||
| using System.Reflection; | |||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Diligent.WebAPI.Shared")] | |||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | |||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | |||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] | |||
| [assembly: System.Reflection.AssemblyProductAttribute("Diligent.WebAPI.Shared")] | |||
| [assembly: System.Reflection.AssemblyTitleAttribute("Diligent.WebAPI.Shared")] | |||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | |||
| // Generated by the MSBuild WriteCodeFragment class. | |||
| @@ -0,0 +1 @@ | |||
| dfb1355104d7a91099e3ba180c907a817966e3c1 | |||
| @@ -0,0 +1,10 @@ | |||
| is_global = true | |||
| build_property.TargetFramework = net6.0 | |||
| build_property.TargetPlatformMinVersion = | |||
| build_property.UsingMicrosoftNETSdkWeb = | |||
| build_property.ProjectTypeGuids = | |||
| build_property.InvariantGlobalization = | |||
| build_property.PlatformNeutralAssembly = | |||
| build_property._SupportedPlatformList = Linux,macOS,Windows | |||
| build_property.RootNamespace = Diligent.WebAPI.Shared | |||
| build_property.ProjectDir = C:\Users\safet.purkovic\source\repos\WebAPI Template - Configuration 1\Diligent.WebAPI.Shared\ | |||
| @@ -0,0 +1,8 @@ | |||
| // <auto-generated/> | |||
| global using global::System; | |||
| global using global::System.Collections.Generic; | |||
| global using global::System.IO; | |||
| global using global::System.Linq; | |||
| global using global::System.Net.Http; | |||
| global using global::System.Threading; | |||
| global using global::System.Threading.Tasks; | |||