Compare commits

8 Commits

Author SHA1 Message Date
Developer 02
3832351dd1 add Jenkinsfile
Some checks failed
AppStd/WorkFlow/pipeline/head There was a failure building this commit
2025-05-22 16:03:12 +02:00
Developer 02
99237cbecc refactor(IISProfile): Verzeichnis aktualisiert, um die Namenskonventionen für digitale Daten anzuwenden 2025-03-25 15:38:33 +01:00
Developer 02
cb2edffe91 chore: Separate IIS-Konfiguration für .Net 7 und 8 hinzufügen 2025-03-24 16:12:39 +01:00
Developer 02
4d3768248e chore: IIS-Veröffentlichungsprofile getrennt nach Framework hinzufügen 2025-03-13 12:06:56 +01:00
Developer 02
fb38bc1fd4 chore(API): Hinzufügen von .net 7-Unterstützung für API 2025-03-13 10:12:55 +01:00
Developer 02
10b557374d chore: Hinzufügen von .net 7-Unterstützung für Domäne, Infrastruktur und Anwendung 2025-03-13 10:04:40 +01:00
Developer 02
f266e6728f chore: Upgrade auf DigitalData.Auth.Client 1.3.3 2025-03-13 09:29:07 +01:00
Developer 02
3373fceef3 chore(API): Hochgestuft auf 1.1.0 2025-03-11 17:17:08 +01:00
28 changed files with 427 additions and 297 deletions

View File

@@ -6,13 +6,15 @@ using WorkFlow.Application.Contracts;
using WorkFlow.Application.DTO.Config; using WorkFlow.Application.DTO.Config;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
namespace WorkFlow.API.Controllers namespace WorkFlow.API.Controllers;
[APIKeyAuth]
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ConfigController : CRUDControllerBaseWithErrorHandling<IConfigService, ConfigCreateDto, ConfigDto, ConfigUpdateDto, Config, int>
{ {
[APIKeyAuth] public ConfigController(ILogger<ConfigController> logger, IConfigService service) : base(logger, service)
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ConfigController(ILogger<ConfigController> logger, IConfigService service) : CRUDControllerBaseWithErrorHandling<IConfigService, ConfigCreateDto, ConfigDto, ConfigUpdateDto, Config, int>(logger, service)
{ {
} }
} }

View File

@@ -6,13 +6,15 @@ using WorkFlow.Application.Contracts;
using WorkFlow.Application.DTO.Profile; using WorkFlow.Application.DTO.Profile;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
namespace WorkFlow.API.Controllers namespace WorkFlow.API.Controllers;
[APIKeyAuth]
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ProfileController : CRUDControllerBaseWithErrorHandling<IProfileService, ProfileCreateDto, ProfileDto, ProfileUpdateDto, Profile, int>
{ {
[APIKeyAuth] public ProfileController(ILogger<ProfileController> logger, IProfileService service) : base(logger, service)
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ProfileController(ILogger<ProfileController> logger, IProfileService service) : CRUDControllerBaseWithErrorHandling<IProfileService, ProfileCreateDto, ProfileDto, ProfileUpdateDto, Profile, int>(logger, service)
{ {
} }
} }

View File

@@ -7,114 +7,120 @@ using WorkFlow.Application.Contracts;
using WorkFlow.Application.DTO.ProfileControlsTF; using WorkFlow.Application.DTO.ProfileControlsTF;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
namespace WorkFlow.API.Controllers namespace WorkFlow.API.Controllers;
[APIKeyAuth]
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ProfileControlsTFController : CRUDControllerBase<IProfileControlsTFService, ProfileControlsTFCreateDto, ProfileControlsTFDto, ProfileControlsTFUpdateDto, ProfileControlsTF, int>
{ {
[APIKeyAuth] private readonly ILogger<ProfileControlsTFController> logger;
[Route("api/[controller]")]
[ApiController] public ProfileControlsTFController(ILogger<ProfileControlsTFController> logger, IProfileControlsTFService service) : base(logger, service)
[Authorize]
public class ProfileControlsTFController(ILogger<ProfileControlsTFController> logger, IProfileControlsTFService service) : CRUDControllerBase<IProfileControlsTFService, ProfileControlsTFCreateDto, ProfileControlsTFDto, ProfileControlsTFUpdateDto, ProfileControlsTF, int>(logger, service)
{ {
[NonAction] this.logger = logger;
public override Task<IActionResult> GetAll() => base.GetAll(); }
[NonAction] [NonAction]
public override Task<IActionResult> Update(ProfileControlsTFUpdateDto updateDto) => base.Update(updateDto); public override Task<IActionResult> GetAll() => base.GetAll();
[HttpGet] [NonAction]
public async Task<IActionResult> GetAsync( public override Task<IActionResult> Update(ProfileControlsTFUpdateDto updateDto) => base.Update(updateDto);
bool withProfile = true, bool withUser = false,
int? profileId = null, int? objId = null, bool? profileActive = null) [HttpGet]
public async Task<IActionResult> GetAsync(
bool withProfile = true, bool withUser = false,
int? profileId = null, int? objId = null, bool? profileActive = null)
{
try
{ {
try if (!this.TryGetUserId(out int? id))
{ {
if (!this.TryGetUserId(out int? id)) logger.LogError("Authorization failed: User ID claim not found.");
{ return StatusCode(StatusCodes.Status500InternalServerError, "Failed to retrieve user identity.");
logger.LogError("Authorization failed: User ID claim not found.");
return StatusCode(StatusCodes.Status500InternalServerError, "Failed to retrieve user identity.");
}
else if (id is null)
{
logger.LogError("Invalid user ID: Retrieved ID is null or not an integer.");
return StatusCode(StatusCodes.Status500InternalServerError, "Invalid user ID.");
}
return await _service.ReadAsync(
withProfile: withProfile, withUser: withUser,
userId: id,
profileId: profileId, objId: objId, profileActive: profileActive)
.ThenAsync(
Success: pctf => pctf.Any() ? Ok(pctf) : NotFound(),
Fail: IActionResult (msg, ntc) =>
{
logger.LogNotice(ntc);
return NotFound();
});
} }
catch (Exception ex) else if (id is null)
{ {
logger.LogError(ex, "An unexpected error occurred while processing the request: {Message}", ex.Message); logger.LogError("Invalid user ID: Retrieved ID is null or not an integer.");
return StatusCode(StatusCodes.Status500InternalServerError, "An internal server error occurred."); return StatusCode(StatusCodes.Status500InternalServerError, "Invalid user ID.");
} }
}
[HttpPost] return await _service.ReadAsync(
public override async Task<IActionResult> Create([FromBody] ProfileControlsTFCreateDto createDto) withProfile: withProfile, withUser: withUser,
{ userId: id,
try profileId: profileId, objId: objId, profileActive: profileActive)
{ .ThenAsync(
if (!this.TryGetUserId(out int? id)) Success: pctf => pctf.Any() ? Ok(pctf) : NotFound(),
{
logger.LogError("Authorization failed: User ID claim not found.");
return StatusCode(StatusCodes.Status500InternalServerError, "Failed to retrieve user identity.");
}
else if (id is null)
{
logger.LogError("Invalid user ID: Retrieved ID is null or not an integer.");
return StatusCode(StatusCodes.Status500InternalServerError, "Invalid user ID.");
}
if (createDto.UserId != id)
return Unauthorized();
return await base.Create(createDto);
}
catch (Exception ex)
{
logger.LogError(ex, "An unexpected error occurred while processing the request: {Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError, "An internal server error occurred.");
}
}
[HttpDelete]
public override async Task<IActionResult> Delete([FromRoute] int id)
{
try
{
if (!this.TryGetUserId(out int? userId))
{
logger.LogError("Authorization failed: User ID claim not found.");
return StatusCode(StatusCodes.Status500InternalServerError, "Failed to retrieve user identity.");
}
else if (userId is null)
{
logger.LogError("Invalid user ID: Retrieved ID is null or not an integer.");
return StatusCode(StatusCodes.Status500InternalServerError, "Invalid user ID.");
}
return await _service.ReadByIdAsync(id).ThenAsync(
SuccessAsync: async pctf => pctf.UserId == userId ? await base.Delete(id) : Unauthorized(),
Fail: IActionResult (msg, ntc) => Fail: IActionResult (msg, ntc) =>
{ {
_logger.LogNotice(ntc); logger.LogNotice(ntc);
return ntc.HasFlag(Flag.NotFound) ? NotFound() : StatusCode(StatusCodes.Status500InternalServerError); return NotFound();
}); });
} }
catch (Exception ex) catch (Exception ex)
{
logger.LogError(ex, "An unexpected error occurred while processing the request: {Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError, "An internal server error occurred.");
}
}
[HttpPost]
public override async Task<IActionResult> Create([FromBody] ProfileControlsTFCreateDto createDto)
{
try
{
if (!this.TryGetUserId(out int? id))
{ {
logger.LogError(ex, "An unexpected error occurred while processing the request: {Message}", ex.Message); logger.LogError("Authorization failed: User ID claim not found.");
return StatusCode(StatusCodes.Status500InternalServerError, "An internal server error occurred."); return StatusCode(StatusCodes.Status500InternalServerError, "Failed to retrieve user identity.");
} }
else if (id is null)
{
logger.LogError("Invalid user ID: Retrieved ID is null or not an integer.");
return StatusCode(StatusCodes.Status500InternalServerError, "Invalid user ID.");
}
if (createDto.UserId != id)
return Unauthorized();
return await base.Create(createDto);
}
catch (Exception ex)
{
logger.LogError(ex, "An unexpected error occurred while processing the request: {Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError, "An internal server error occurred.");
}
}
[HttpDelete]
public override async Task<IActionResult> Delete([FromRoute] int id)
{
try
{
if (!this.TryGetUserId(out int? userId))
{
logger.LogError("Authorization failed: User ID claim not found.");
return StatusCode(StatusCodes.Status500InternalServerError, "Failed to retrieve user identity.");
}
else if (userId is null)
{
logger.LogError("Invalid user ID: Retrieved ID is null or not an integer.");
return StatusCode(StatusCodes.Status500InternalServerError, "Invalid user ID.");
}
return await _service.ReadByIdAsync(id).ThenAsync(
SuccessAsync: async pctf => pctf.UserId == userId ? await base.Delete(id) : Unauthorized(),
Fail: IActionResult (msg, ntc) =>
{
_logger.LogNotice(ntc);
return ntc.HasFlag(Flag.NotFound) ? NotFound() : StatusCode(StatusCodes.Status500InternalServerError);
});
}
catch (Exception ex)
{
logger.LogError(ex, "An unexpected error occurred while processing the request: {Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError, "An internal server error occurred.");
} }
} }
} }

View File

@@ -13,8 +13,15 @@ namespace WorkFlow.API.Controllers
[Route("api/[controller]")] [Route("api/[controller]")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class ProfileObjStateController(ILogger<ProfileObjStateController> logger, IProfileObjStateService service) : CRUDControllerBaseWithErrorHandling<IProfileObjStateService, ProfileObjStateCreateDto, ProfileObjStateDto, ProfileObjStateUpdateDto, ProfileObjState, int>(logger, service) public class ProfileObjStateController : CRUDControllerBaseWithErrorHandling<IProfileObjStateService, ProfileObjStateCreateDto, ProfileObjStateDto, ProfileObjStateUpdateDto, ProfileObjState, int>
{ {
private readonly ILogger<ProfileObjStateController> logger;
public ProfileObjStateController(ILogger<ProfileObjStateController> logger, IProfileObjStateService service) : base(logger, service)
{
this.logger = logger;
}
[NonAction] [NonAction]
public override Task<IActionResult> GetAll() => base.GetAll(); public override Task<IActionResult> GetAll() => base.GetAll();

View File

@@ -6,13 +6,15 @@ using WorkFlow.Application.Contracts;
using WorkFlow.Application.DTO.State; using WorkFlow.Application.DTO.State;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
namespace WorkFlow.API.Controllers namespace WorkFlow.API.Controllers;
[APIKeyAuth]
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class StateController : CRUDControllerBaseWithErrorHandling<IStateService, StateCreateDto, StateDto, StateUpdateDto, State, int>
{ {
[APIKeyAuth] public StateController(ILogger<StateController> logger, IStateService service) : base(logger, service)
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class StateController(ILogger<StateController> logger, IStateService service) : CRUDControllerBaseWithErrorHandling<IStateService, StateCreateDto, StateDto, StateUpdateDto, State, int>(logger, service)
{ {
} }
} }

View File

@@ -4,43 +4,51 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using WorkFlow.API.Attributes; using WorkFlow.API.Attributes;
namespace WorkFlow.API.Controllers namespace WorkFlow.API.Controllers;
[APIKeyAuth]
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class UserController : ControllerBase
{ {
[APIKeyAuth] private readonly ILogger<UserController> logger;
[Route("api/[controller]")] private readonly IUserService userService;
[ApiController]
[Authorize] public UserController(ILogger<UserController> logger, IUserService userService)
public class UserController(ILogger<UserController> logger, IUserService userService) : ControllerBase
{ {
[HttpGet] this.logger = logger;
public async Task<IActionResult> GetAsync() this.userService = userService;
}
[HttpGet]
public async Task<IActionResult> GetAsync()
{
try
{ {
try if (!this.TryGetUserId(out int? id))
{ {
if (!this.TryGetUserId(out int? id)) logger.LogError("Authorization failed: User ID claim not found.");
{ return StatusCode(StatusCodes.Status500InternalServerError, "Failed to retrieve user identity.");
logger.LogError("Authorization failed: User ID claim not found.");
return StatusCode(StatusCodes.Status500InternalServerError, "Failed to retrieve user identity.");
}
else if(id is int id_int)
return await userService.ReadByIdAsync(id_int).ThenAsync(
Success: Ok,
Fail: IActionResult (msg, ntc) =>
{
logger.LogNotice(ntc);
return NotFound();
});
else
{
logger.LogError("Invalid user ID: Retrieved ID is null or not an integer.");
return StatusCode(StatusCodes.Status500InternalServerError, "Invalid user ID.");
}
} }
catch (Exception ex) else if(id is int id_int)
return await userService.ReadByIdAsync(id_int).ThenAsync(
Success: Ok,
Fail: IActionResult (msg, ntc) =>
{
logger.LogNotice(ntc);
return NotFound();
});
else
{ {
logger.LogError(ex, "An unexpected error occurred while processing the request: {Message}", ex.Message); logger.LogError("Invalid user ID: Retrieved ID is null or not an integer.");
return StatusCode(StatusCodes.Status500InternalServerError, "An internal server error occurred."); return StatusCode(StatusCodes.Status500InternalServerError, "Invalid user ID.");
} }
} }
catch (Exception ex)
{
logger.LogError(ex, "An unexpected error occurred while processing the request: {Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError, "An internal server error occurred.");
}
} }
} }

View File

@@ -4,33 +4,39 @@ using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerGen;
using WorkFlow.API.Models; using WorkFlow.API.Models;
namespace WorkFlow.API.Filters namespace WorkFlow.API.Filters;
public class APIKeyAuthHeaderOpFilter : IOperationFilter
{ {
public class APIKeyAuthHeaderOpFilter(IOptions<APIKeyAuthOptions> options, IWebHostEnvironment environment) : IOperationFilter private readonly APIKeyAuthOptions apiKeyAuthOptions;
private readonly IWebHostEnvironment environment;
public APIKeyAuthHeaderOpFilter(IOptions<APIKeyAuthOptions> options, IWebHostEnvironment environment)
{ {
private readonly APIKeyAuthOptions apiKeyAuthOptions = options.Value; this.environment = environment;
apiKeyAuthOptions = options.Value;
}
public void Apply(OpenApiOperation operation, OperationFilterContext context) public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var param = new OpenApiParameter
{ {
var param = new OpenApiParameter Name = apiKeyAuthOptions.HeaderName,
In = ParameterLocation.Header,
Required = true,
AllowEmptyValue = false,
Schema = new OpenApiSchema
{ {
Name = apiKeyAuthOptions.HeaderName, Type = "string"
In = ParameterLocation.Header, }
Required = true, };
AllowEmptyValue = false,
Schema = new OpenApiSchema
{
Type = "string"
}
};
if(environment.IsDevelopment()) if(environment.IsDevelopment())
param.Schema.Default = new OpenApiString(apiKeyAuthOptions.Key); param.Schema.Default = new OpenApiString(apiKeyAuthOptions.Key);
if (apiKeyAuthOptions.SwaggerDescription is not null) if (apiKeyAuthOptions.SwaggerDescription is not null)
param.Description = apiKeyAuthOptions.SwaggerDescription; param.Description = apiKeyAuthOptions.SwaggerDescription;
operation.Parameters.Add(param); operation.Parameters.Add(param);
}
} }
} }

View File

@@ -1,14 +1,22 @@
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace WorkFlow.API.Filters namespace WorkFlow.API.Filters;
public class APIKeyAuthFilter : IAuthorizationFilter
{ {
public class APIKeyAuthFilter(Func<string?, bool> isValidKey, string headerName = "X-API-Key") : IAuthorizationFilter private readonly Func<string?, bool> isValidKey;
private readonly string headerName;
public APIKeyAuthFilter(Func<string?, bool> isValidKey, string headerName = "X-API-Key")
{ {
public void OnAuthorization(AuthorizationFilterContext context) this.isValidKey = isValidKey;
{ this.headerName = headerName;
if (!isValidKey(context.HttpContext.Request.Headers[headerName])) }
context.Result = new UnauthorizedResult();
} public void OnAuthorization(AuthorizationFilterContext context)
{
if (!isValidKey(context.HttpContext.Request.Headers[headerName]))
context.Result = new UnauthorizedResult();
} }
} }

10
WorkFlow.API/Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,10 @@
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'dotnet build'
}
}
}
}

View File

@@ -5,13 +5,14 @@ namespace WorkFlow.API.Models
{ {
public static class ModelExtensions public static class ModelExtensions
{ {
public static List<Claim> ToClaimList(this UserReadDto user) => [ public static List<Claim> ToClaimList(this UserReadDto user) => new()
{
new (ClaimTypes.NameIdentifier, user.Id.ToString()), new (ClaimTypes.NameIdentifier, user.Id.ToString()),
new (ClaimTypes.Name, user.Username), new (ClaimTypes.Name, user.Username),
new (ClaimTypes.Surname, user.Name ?? ""), new (ClaimTypes.Surname, user.Name ?? ""),
new (ClaimTypes.GivenName, user.Prename ?? ""), new (ClaimTypes.GivenName, user.Prename ?? ""),
new (ClaimTypes.Email, user.Email ?? "") new (ClaimTypes.Email, user.Email ?? "")
]; };
public static Dictionary<string, object> ToClaimDictionary(this UserReadDto user) => user.ToClaimList().ToDictionary(claim => claim.Type, claim => (object) claim.Value); public static Dictionary<string, object> ToClaimDictionary(this UserReadDto user) => user.ToClaimList().ToDictionary(claim => claim.Type, claim => (object) claim.Value);
} }

View File

@@ -72,7 +72,7 @@ try
{ {
var clientParams = lazyProvider.GetRequiredService<IOptions<ClientParams>>()?.Value; var clientParams = lazyProvider.GetRequiredService<IOptions<ClientParams>>()?.Value;
var publicKey = clientParams!.PublicKeys.Get(authTokenKeys.Issuer, authTokenKeys.Audience); var publicKey = clientParams!.PublicKeys.Get(authTokenKeys.Issuer, authTokenKeys.Audience);
return [publicKey.SecurityKey]; return new List<SecurityKey>() { publicKey.SecurityKey };
}, },
ValidateIssuer = true, ValidateIssuer = true,
ValidIssuer = authTokenKeys.Issuer, ValidIssuer = authTokenKeys.Issuer,

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<WebPublishMethod>Package</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<ExcludeApp_Data>false</ExcludeApp_Data>
<ProjectGuid>4fb33592-ef0d-47c3-9cde-03b2ef12be00</ProjectGuid>
<DesktopBuildPackageLocation>P:\Install .Net\0 DD - Smart UP\workFLOW\API\net7\$(Version)\workFLOW.API.zip</DesktopBuildPackageLocation>
<PackageAsSingleFile>true</PackageAsSingleFile>
<DeployIisAppPath>WorkFlow.API</DeployIisAppPath>
<_TargetId>IISWebDeployPackage</_TargetId>
<TargetFramework>net7.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<WebPublishMethod>Package</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<ExcludeApp_Data>false</ExcludeApp_Data>
<ProjectGuid>4fb33592-ef0d-47c3-9cde-03b2ef12be00</ProjectGuid>
<DesktopBuildPackageLocation>P:\Install .Net\0 DD - Smart UP\workFLOW\API\net8\$(Version)\workFLOW.API.zip</DesktopBuildPackageLocation>
<PackageAsSingleFile>true</PackageAsSingleFile>
<DeployIisAppPath>WorkFlow.API</DeployIisAppPath>
<_TargetId>IISWebDeployPackage</_TargetId>
<TargetFramework>net7.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
</PropertyGroup>
</Project>

View File

@@ -1,20 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<PackageId>1.0.0.0</PackageId> <PackageId>WorkFlow.API</PackageId>
<Version>1.0.0.0</Version> <Version>1.1.0</Version>
<Company>Digital Data GmbH</Company> <Company>Digital Data GmbH</Company>
<Product>WorkFlow.API</Product> <Product>WorkFlow.API</Product>
<Title>WorkFlow.API</Title> <Title>WorkFlow.API</Title>
<AssemblyVersion>1.1.0</AssemblyVersion>
<FileVersion>1.1.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DigitalData.Auth.Client" Version="1.2.1.1" /> <_WebToolingArtifacts Remove="Properties\PublishProfiles\IISProfile - Copy.pubxml" />
<_WebToolingArtifacts Remove="Properties\PublishProfiles\IISProfileNet7.pubxml" />
<_WebToolingArtifacts Remove="Properties\PublishProfiles\IISProfileNet8.pubxml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Auth.Client" Version="1.3.3" />
<PackageReference Include="DigitalData.Core.API" Version="2.1.1" /> <PackageReference Include="DigitalData.Core.API" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.13" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.20" />
<PackageReference Include="NLog" Version="5.3.4" /> <PackageReference Include="NLog" Version="5.3.4" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.14" /> <PackageReference Include="NLog.Web.AspNetCore" Version="5.3.14" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />

View File

@@ -6,11 +6,12 @@ using WorkFlow.Application.DTO.Config;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
using WorkFlow.Infrastructure.Contracts; using WorkFlow.Infrastructure.Contracts;
namespace WorkFlow.Application.Services namespace WorkFlow.Application.Services;
public class ConfigService : CRUDService<IConfigRepository, ConfigCreateDto, ConfigDto, Config, int>,
IConfigService, ICRUDService<ConfigCreateDto, ConfigDto, Config, int>
{ {
public class ConfigService(IConfigRepository repository, IMapper mapper) public ConfigService(IConfigRepository repository, IMapper mapper) : base(repository, mapper)
: CRUDService<IConfigRepository, ConfigCreateDto, ConfigDto, Config, int>(repository, mapper),
IConfigService, ICRUDService<ConfigCreateDto, ConfigDto, Config, int>
{ {
} }
} }

View File

@@ -9,10 +9,13 @@ using WorkFlow.Infrastructure.Contracts;
namespace WorkFlow.Application.Services namespace WorkFlow.Application.Services
{ {
public class ProfileControlsTFService(IProfileControlsTFRepository repository, IMapper mapper) public class ProfileControlsTFService : CRUDService<IProfileControlsTFRepository, ProfileControlsTFCreateDto, ProfileControlsTFDto, ProfileControlsTF, int>,
: CRUDService<IProfileControlsTFRepository, ProfileControlsTFCreateDto, ProfileControlsTFDto, ProfileControlsTF, int>(repository, mapper),
IProfileControlsTFService, ICRUDService<ProfileControlsTFCreateDto, ProfileControlsTFDto, ProfileControlsTF, int> IProfileControlsTFService, ICRUDService<ProfileControlsTFCreateDto, ProfileControlsTFDto, ProfileControlsTF, int>
{ {
public ProfileControlsTFService(IProfileControlsTFRepository repository, IMapper mapper) : base(repository, mapper)
{
}
public async Task<DataResult<IEnumerable<ProfileControlsTFDto>>> ReadAsync( public async Task<DataResult<IEnumerable<ProfileControlsTFDto>>> ReadAsync(
bool withProfile = true, bool withUser = false, bool withProfile = true, bool withUser = false,
int? userId = null, string? username = null, int? userId = null, string? username = null,

View File

@@ -7,26 +7,28 @@ using WorkFlow.Application.DTO.ProfileObjState;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
using WorkFlow.Infrastructure.Contracts; using WorkFlow.Infrastructure.Contracts;
namespace WorkFlow.Application.Services namespace WorkFlow.Application.Services;
public class ProfileObjStateService : CRUDService<IProfileObjStateRepository, ProfileObjStateCreateDto, ProfileObjStateDto, ProfileObjState, int>,
IProfileObjStateService, ICRUDService<ProfileObjStateCreateDto, ProfileObjStateDto, ProfileObjState, int>
{ {
public class ProfileObjStateService(IProfileObjStateRepository repository, IMapper mapper) public ProfileObjStateService(IProfileObjStateRepository repository, IMapper mapper) : base(repository, mapper)
: CRUDService<IProfileObjStateRepository, ProfileObjStateCreateDto, ProfileObjStateDto, ProfileObjState, int>(repository, mapper),
IProfileObjStateService, ICRUDService<ProfileObjStateCreateDto, ProfileObjStateDto, ProfileObjState, int>
{ {
public async Task<DataResult<IEnumerable<ProfileObjStateDto>>> ReadAsync( }
bool withProfile = true, bool withUser = true, bool withState = true,
int? userId = null, string? username = null,
int? profileId = null, int? objId = null, bool? profileActive = null)
{
var pos_list = await _repository.ReadAsync(
isReadonly: true,
withProfile: withProfile, withUser: withUser, withState: withState,
userId: userId, username: username,
profileId: profileId, objId: objId, profileActive: profileActive);
var post_dto_list = _mapper.Map<IEnumerable<ProfileObjStateDto>>(pos_list); public async Task<DataResult<IEnumerable<ProfileObjStateDto>>> ReadAsync(
bool withProfile = true, bool withUser = true, bool withState = true,
int? userId = null, string? username = null,
int? profileId = null, int? objId = null, bool? profileActive = null)
{
var pos_list = await _repository.ReadAsync(
isReadonly: true,
withProfile: withProfile, withUser: withUser, withState: withState,
userId: userId, username: username,
profileId: profileId, objId: objId, profileActive: profileActive);
return Result.Success(post_dto_list); var post_dto_list = _mapper.Map<IEnumerable<ProfileObjStateDto>>(pos_list);
}
return Result.Success(post_dto_list);
} }
} }

View File

@@ -5,11 +5,12 @@ using WorkFlow.Application.DTO.Profile;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
using WorkFlow.Infrastructure.Contracts; using WorkFlow.Infrastructure.Contracts;
namespace WorkFlow.Application.Services namespace WorkFlow.Application.Services;
public class ProfileService : CRUDService<IProfileRepository, ProfileCreateDto, ProfileDto, Profile, int>,
IProfileService, ICRUDService<ProfileCreateDto, ProfileDto, Profile, int>
{ {
public class ProfileService(IProfileRepository repository, AutoMapper.IMapper mapper) public ProfileService(IProfileRepository repository, AutoMapper.IMapper mapper) : base(repository, mapper)
: CRUDService<IProfileRepository, ProfileCreateDto, ProfileDto, Profile, int>(repository, mapper),
IProfileService, ICRUDService<ProfileCreateDto, ProfileDto, Profile, int>
{ {
} }
} }

View File

@@ -6,11 +6,12 @@ using WorkFlow.Application.DTO.State;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
using WorkFlow.Infrastructure.Contracts; using WorkFlow.Infrastructure.Contracts;
namespace WorkFlow.Application.Services namespace WorkFlow.Application.Services;
public class StateService : CRUDService<IStateRepository, StateCreateDto, StateDto, State, int>,
IStateService, ICRUDService<StateCreateDto, StateDto, State, int>
{ {
public class StateService(IStateRepository repository, IMapper mapper) public StateService(IStateRepository repository, IMapper mapper) : base(repository, mapper)
: CRUDService<IStateRepository, StateCreateDto, StateDto, State, int>(repository, mapper),
IStateService, ICRUDService<StateCreateDto, StateDto, State, int>
{ {
} }
} }

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>

View File

@@ -6,7 +6,10 @@ using WorkFlow.Infrastructure.Contracts;
namespace WorkFlow.Infrastructure.Repositories namespace WorkFlow.Infrastructure.Repositories
{ {
//TODO: Make the db context type generic so that it can be used by other projects with different db contexts. //TODO: Make the db context type generic so that it can be used by other projects with different db contexts.
public class ConfigRepository(WFDBContext dbContext) : CRUDRepository<Config, int, WFDBContext>(dbContext, dbContext.Configs), IConfigRepository, ICRUDRepository<Config, int> public class ConfigRepository : CRUDRepository<Config, int, WFDBContext>, IConfigRepository, ICRUDRepository<Config, int>
{ {
public ConfigRepository(WFDBContext dbContext) : base(dbContext, dbContext.Configs)
{
}
} }
} }

View File

@@ -6,8 +6,12 @@ using WorkFlow.Infrastructure.Contracts;
namespace WorkFlow.Infrastructure.Repositories namespace WorkFlow.Infrastructure.Repositories
{ {
public class ProfileControlsTFRepository(WFDBContext dbContext) : CRUDRepository<ProfileControlsTF, int, WFDBContext>(dbContext, dbContext.ProfileControlsTFs), IProfileControlsTFRepository, ICRUDRepository<ProfileControlsTF, int> public class ProfileControlsTFRepository : CRUDRepository<ProfileControlsTF, int, WFDBContext>, IProfileControlsTFRepository, ICRUDRepository<ProfileControlsTF, int>
{ {
public ProfileControlsTFRepository(WFDBContext dbContext) : base(dbContext, dbContext.ProfileControlsTFs)
{
}
protected override IQueryable<ProfileControlsTF> ReadOnly() => base.ReadOnly().Include(pctf => pctf.Profile).Include(pctf => pctf.User); protected override IQueryable<ProfileControlsTF> ReadOnly() => base.ReadOnly().Include(pctf => pctf.Profile).Include(pctf => pctf.User);
protected IQueryable<ProfileControlsTF> Read(bool isReadonly = false, bool withProfile = true, bool withUser = true, int? profileId = null, int? userId = null, string? username = null, int? objId = null, bool? profileActive = null) protected IQueryable<ProfileControlsTF> Read(bool isReadonly = false, bool withProfile = true, bool withUser = true, int? profileId = null, int? userId = null, string? username = null, int? objId = null, bool? profileActive = null)

View File

@@ -4,56 +4,59 @@ using Microsoft.EntityFrameworkCore;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
using WorkFlow.Infrastructure.Contracts; using WorkFlow.Infrastructure.Contracts;
namespace WorkFlow.Infrastructure.Repositories namespace WorkFlow.Infrastructure.Repositories;
public class ProfileObjStateRepository : CRUDRepository<ProfileObjState, int, WFDBContext>, IProfileObjStateRepository, ICRUDRepository<ProfileObjState, int>
{ {
public class ProfileObjStateRepository(WFDBContext dbContext) : CRUDRepository<ProfileObjState, int, WFDBContext>(dbContext, dbContext.ProfileObjStates), IProfileObjStateRepository, ICRUDRepository<ProfileObjState, int> public ProfileObjStateRepository(WFDBContext dbContext) : base(dbContext, dbContext.ProfileObjStates)
{ {
protected override IQueryable<ProfileObjState> ReadOnly() => base.ReadOnly().Include(pos => pos.Profile).Include(pos => pos.State);
protected IQueryable<ProfileObjState> Read(bool isReadonly = false, bool withProfile = true, bool withUser = true, bool withState = true, int? profileId = null, int? userId = null, string? username = null, int? stateId = null, int? objId = null, bool? profileActive = null)
{
var query = isReadonly ? _dbSet.AsNoTracking() : _dbSet.AsQueryable();
if (withProfile)
query = query.Include(pctf => pctf.Profile);
if (withUser)
query = query.Include(pctf => pctf.User);
if (withState)
query = query.Include(pctf => pctf.State);
if (profileId is not null)
query = query.Where(pctf => pctf.ProfileId == profileId);
if (userId is not null)
query = query.Where(pctf => pctf.UserId == userId);
if (username is null)
query = query.Where(pctf => pctf.User!.Username == username);
if (stateId is null)
query = query.Where(pctf => pctf.State!.Id == stateId);
if (objId is not null)
query = query.Where(pctf => pctf.ObjId == objId);
if (profileActive is not null)
query = query.Where(pctf => pctf.Profile!.Active == profileActive);
return query;
}
public async Task<IEnumerable<ProfileObjState>> ReadAsync(
bool isReadonly = true,
bool withProfile = true, bool withUser = true, bool withState = true,
int? userId = null, string? username = null,
int? profileId = null, int? objId = null, bool? profileActive = null)
=> await Read(
isReadonly: isReadonly,
withProfile: withProfile, withUser: withUser, withState: withState,
userId: userId, username: username,
profileId: profileId, objId: objId, profileActive: profileActive)
.ToListAsync();
} }
protected override IQueryable<ProfileObjState> ReadOnly() => base.ReadOnly().Include(pos => pos.Profile).Include(pos => pos.State);
protected IQueryable<ProfileObjState> Read(bool isReadonly = false, bool withProfile = true, bool withUser = true, bool withState = true, int? profileId = null, int? userId = null, string? username = null, int? stateId = null, int? objId = null, bool? profileActive = null)
{
var query = isReadonly ? _dbSet.AsNoTracking() : _dbSet.AsQueryable();
if (withProfile)
query = query.Include(pctf => pctf.Profile);
if (withUser)
query = query.Include(pctf => pctf.User);
if (withState)
query = query.Include(pctf => pctf.State);
if (profileId is not null)
query = query.Where(pctf => pctf.ProfileId == profileId);
if (userId is not null)
query = query.Where(pctf => pctf.UserId == userId);
if (username is null)
query = query.Where(pctf => pctf.User!.Username == username);
if (stateId is null)
query = query.Where(pctf => pctf.State!.Id == stateId);
if (objId is not null)
query = query.Where(pctf => pctf.ObjId == objId);
if (profileActive is not null)
query = query.Where(pctf => pctf.Profile!.Active == profileActive);
return query;
}
public async Task<IEnumerable<ProfileObjState>> ReadAsync(
bool isReadonly = true,
bool withProfile = true, bool withUser = true, bool withState = true,
int? userId = null, string? username = null,
int? profileId = null, int? objId = null, bool? profileActive = null)
=> await Read(
isReadonly: isReadonly,
withProfile: withProfile, withUser: withUser, withState: withState,
userId: userId, username: username,
profileId: profileId, objId: objId, profileActive: profileActive)
.ToListAsync();
} }

View File

@@ -3,9 +3,11 @@ using DigitalData.Core.Infrastructure;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
using WorkFlow.Infrastructure.Contracts; using WorkFlow.Infrastructure.Contracts;
namespace WorkFlow.Infrastructure.Repositories namespace WorkFlow.Infrastructure.Repositories;
public class ProfileRepository : CRUDRepository<Profile, int, WFDBContext>, IProfileRepository, ICRUDRepository<Profile, int>
{ {
public class ProfileRepository(WFDBContext dbContext) : CRUDRepository<Profile, int, WFDBContext>(dbContext, dbContext.Profiles), IProfileRepository, ICRUDRepository<Profile, int> public ProfileRepository(WFDBContext dbContext) : base(dbContext, dbContext.Profiles)
{ {
} }
} }

View File

@@ -2,9 +2,12 @@
using DigitalData.Core.Infrastructure; using DigitalData.Core.Infrastructure;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
using WorkFlow.Infrastructure.Contracts; using WorkFlow.Infrastructure.Contracts;
namespace WorkFlow.Infrastructure.Repositories
namespace WorkFlow.Infrastructure.Repositories;
public class StateRepository : CRUDRepository<State, int, WFDBContext>, IStateRepository, ICRUDRepository<State, int>
{ {
public class StateRepository(WFDBContext dbContext) : CRUDRepository<State, int, WFDBContext>(dbContext, dbContext.States), IStateRepository, ICRUDRepository<State, int> public StateRepository(WFDBContext dbContext) : base(dbContext, dbContext.States)
{ {
} }
} }

View File

@@ -4,40 +4,43 @@ using DigitalData.UserManager.Infrastructure.Contracts;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using WorkFlow.Domain.Entities; using WorkFlow.Domain.Entities;
namespace WorkFlow.Infrastructure namespace WorkFlow.Infrastructure;
public class WFDBContext : DbContext, IUserManagerDbContext
{ {
public class WFDBContext(DbContextOptions options) : DbContext(options), IUserManagerDbContext public DbSet<Config> Configs { get; set; }
public DbSet<ProfileControlsTF> ProfileControlsTFs { get; set; }
public DbSet<Profile> Profiles { get; set; }
public DbSet<ProfileObjState> ProfileObjStates { get; set; }
public DbSet<State> States { get; set; }
public DbSet<GroupOfUser> GroupOfUsers { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<ModuleOfUser> ModuleOfUsers { get; set; }
public DbSet<Module> Modules { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<UserRep> UserReps { get; set; }
public DbSet<ClientUser> ClientUsers { get; set; }
public WFDBContext(DbContextOptions options) : base(options)
{ {
public DbSet<Config> Configs { get; set; } }
public DbSet<ProfileControlsTF> ProfileControlsTFs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//configure model builder for user manager tables
modelBuilder.ConfigureUserManager();
public DbSet<Profile> Profiles { get; set; } base.OnModelCreating(modelBuilder);
public DbSet<ProfileObjState> ProfileObjStates { get; set; }
public DbSet<State> States { get; set; }
public DbSet<GroupOfUser> GroupOfUsers { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<ModuleOfUser> ModuleOfUsers { get; set; }
public DbSet<Module> Modules { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<UserRep> UserReps { get; set; }
public DbSet<ClientUser> ClientUsers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//configure model builder for user manager tables
modelBuilder.ConfigureUserManager();
base.OnModelCreating(modelBuilder);
}
} }
} }

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>