Compare commits
152 Commits
fb12cb6c98
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 27d731a5b0 | |||
| b8f797f14d | |||
| 6feef53733 | |||
| 878e096c57 | |||
| 2ded140ad5 | |||
| e2ca249d13 | |||
| e782eab62a | |||
| d8e08b237d | |||
|
|
88cb1dc16a | ||
|
|
8d6a09213e | ||
|
|
54f412ced2 | ||
|
|
51b9c62188 | ||
|
|
bb5525778d | ||
|
|
ee793632df | ||
|
|
22bb585f60 | ||
|
|
ed7237c8dd | ||
|
|
f71bcf37e9 | ||
|
|
c7e366af60 | ||
| 86f4e3141e | |||
| 869ba9858f | |||
| 5dee104377 | |||
| 36e1d5fad1 | |||
| 304490d661 | |||
| ff4ab9efe2 | |||
| 470120e5e9 | |||
| ce35ef588f | |||
| df665e3b98 | |||
| 4bc6df4d91 | |||
| 383932e7e7 | |||
| e3494d50b7 | |||
| 5197ad1481 | |||
| dbfb7e7e47 | |||
| b9a40bb12e | |||
| 8ddaf1d13e | |||
| 14532a15bf | |||
| 0149a77f21 | |||
| a17d260c6c | |||
| b639df0a39 | |||
| 0fddf5669f | |||
| 9c46b9f2da | |||
| 87d9769d9b | |||
| 19ecf104fa | |||
| 5b5b034e78 | |||
| 5ebb3f72e3 | |||
| 3cfecbf598 | |||
| 4895b9c8f8 | |||
| 36fe78e152 | |||
| 489180f5a1 | |||
| b65810bbbb | |||
| 278fcfd75b | |||
| 41db75b183 | |||
| f4a921e268 | |||
| cdb52dc6fd | |||
| f14f6c1f15 | |||
| 6a24719342 | |||
| 631ab8cba5 | |||
| 872878b9d7 | |||
| 5a30b0ece4 | |||
| 37200617ea | |||
| 8ab66db1f2 | |||
| cbd52721ac | |||
| 3003559d7a | |||
| 6cabdbb6a3 | |||
| 4dd54e206e | |||
| 84cf5c8e4d | |||
| 84d6e7a511 | |||
| 89238cc2d1 | |||
| 7b177f21c8 | |||
| 2deb235c8d | |||
| c452724c9e | |||
| 13e65774cc | |||
| f2d2dc9a32 | |||
| 459620e1dd | |||
| df2541108b | |||
| 5dcd5313a5 | |||
| ef9d725f59 | |||
| 6f4ab073df | |||
| f6b95331e1 | |||
| 82de285891 | |||
|
|
cbd86de3e8 | ||
|
|
a5160b35dd | ||
|
|
60e1627494 | ||
|
|
b9f08bc21c | ||
|
|
758616c95e | ||
|
|
7376b49e38 | ||
|
|
b65c354ef0 | ||
|
|
38258a98c1 | ||
|
|
7666708ab5 | ||
|
|
d3b67bc429 | ||
|
|
97f992aef5 | ||
|
|
cc6f93ae1c | ||
|
|
402990bd3c | ||
|
|
43cdef4910 | ||
|
|
348a55fc60 | ||
|
|
719bc9c941 | ||
|
|
37381af042 | ||
|
|
34fe996d91 | ||
|
|
252fc10243 | ||
|
|
c8a9245b54 | ||
|
|
c56bcc198e | ||
|
|
538abec212 | ||
|
|
19666e649d | ||
|
|
1df9235036 | ||
| dd9c1c7ca2 | |||
| f9cc735318 | |||
| 2a8eb3c0ad | |||
| 7a4cdb3d1f | |||
| 453b6d1813 | |||
| bd2b5ff62f | |||
| 849de7a204 | |||
| c7423fb6fd | |||
| ad51e4b1eb | |||
| df2ebe0cc2 | |||
| 5c06f287ab | |||
| c3e3a0377d | |||
| cf34a54170 | |||
| 16f48f125b | |||
| e3faa2f570 | |||
| 0d30b5ff87 | |||
| 563375f6e3 | |||
| 3864b0f68b | |||
| 35e03269e7 | |||
| 8b212d541e | |||
| dd4cecc15d | |||
| 0dedb506e1 | |||
| 24f146ca26 | |||
| 2692553865 | |||
| d90c2fab96 | |||
| 854e36e71f | |||
| 1d31f2aff9 | |||
| 11206cf84f | |||
| b48ebd8e88 | |||
| 12d17e0808 | |||
| 1dee3180d5 | |||
| bd4046a6c1 | |||
| af6f94c1ed | |||
| 7bfb56b664 | |||
| 1a6eced316 | |||
| c82749bcbf | |||
| e8fa149532 | |||
| aaa7beb92a | |||
| 5cce52ec27 | |||
| 3f36f048b2 | |||
| 92e8d9e778 | |||
| 2d04670fef | |||
| c0085b4c18 | |||
| 59ea5e3e67 | |||
| a9f2c4c2f7 | |||
| 001f4bf2c5 | |||
| bfe6c12ee0 | |||
| e1260e49f0 | |||
| 8b86eca838 |
28
ReC.sln
28
ReC.sln
@@ -20,6 +20,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
assets\icon.png = assets\icon.png
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "infrastructure", "infrastructure", "{3F88DACC-CEC0-4D9A-8BAA-37F67B02DC04}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "presentation", "presentation", "{3D6EF9B9-D00D-432A-8477-067902B5CE8E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{2CEF945E-94D6-4273-9BE1-20B628CD0A57}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{8353C9B1-CC4A-4097-A936-C06D4C618415}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReC.Tests", "tests\ReC.Tests\ReC.Tests.csproj", "{457ED5AC-F4A0-41C3-9758-4A3C272EDC11}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -46,16 +56,24 @@ Global
|
||||
{DA3A6BDD-8045-478F-860B-D1F0EB97F02B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DA3A6BDD-8045-478F-860B-D1F0EB97F02B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DA3A6BDD-8045-478F-860B-D1F0EB97F02B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{457ED5AC-F4A0-41C3-9758-4A3C272EDC11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{457ED5AC-F4A0-41C3-9758-4A3C272EDC11}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{457ED5AC-F4A0-41C3-9758-4A3C272EDC11}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{457ED5AC-F4A0-41C3-9758-4A3C272EDC11}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{420218AD-3C27-4003-9A84-36C92352F175} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{2917BEA4-6C70-40CD-BD46-57D4ADB40296} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{587A4D14-EFDA-4BE3-8912-D3AF84743079} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{109645F5-441D-476B-B7D2-FBEAA8EBAE14} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{DA3A6BDD-8045-478F-860B-D1F0EB97F02B} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{420218AD-3C27-4003-9A84-36C92352F175} = {3D6EF9B9-D00D-432A-8477-067902B5CE8E}
|
||||
{2917BEA4-6C70-40CD-BD46-57D4ADB40296} = {2CEF945E-94D6-4273-9BE1-20B628CD0A57}
|
||||
{587A4D14-EFDA-4BE3-8912-D3AF84743079} = {3F88DACC-CEC0-4D9A-8BAA-37F67B02DC04}
|
||||
{109645F5-441D-476B-B7D2-FBEAA8EBAE14} = {2CEF945E-94D6-4273-9BE1-20B628CD0A57}
|
||||
{DA3A6BDD-8045-478F-860B-D1F0EB97F02B} = {3D6EF9B9-D00D-432A-8477-067902B5CE8E}
|
||||
{3F88DACC-CEC0-4D9A-8BAA-37F67B02DC04} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{3D6EF9B9-D00D-432A-8477-067902B5CE8E} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{2CEF945E-94D6-4273-9BE1-20B628CD0A57} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{457ED5AC-F4A0-41C3-9758-4A3C272EDC11} = {8353C9B1-CC4A-4097-A936-C06D4C618415}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {F7B09104-4072-4635-9492-9C7C68D96ABD}
|
||||
|
||||
33
src/ReC.API/Controllers/CommonController.cs
Normal file
33
src/ReC.API/Controllers/CommonController.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
|
||||
namespace ReC.API.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class CommonController(IMediator mediator) : ControllerBase
|
||||
{
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreateObject([FromBody] InsertObjectProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
var id = await mediator.Send(procedure, cancel);
|
||||
return StatusCode(StatusCodes.Status201Created, id);
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
public async Task<IActionResult> UpdateObject([FromBody] UpdateObjectProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
var result = await mediator.Send(procedure, cancel);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
public async Task<IActionResult> DeleteObject([FromBody] DeleteObjectProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
var result = await mediator.Send(procedure, cancel);
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
56
src/ReC.API/Controllers/EndpointAuthController.cs
Normal file
56
src/ReC.API/Controllers/EndpointAuthController.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.EndpointAuth.Commands;
|
||||
|
||||
namespace ReC.API.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class EndpointAuthController(IMediator mediator, IConfiguration config) : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Inserts an endpoint authentication record via the ENDPOINT_AUTH insert procedure.
|
||||
/// </summary>
|
||||
/// <param name="procedure">InsertEndpointAuthProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The created ENDPOINT_AUTH identifier.</returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||
public async Task<IActionResult> Post([FromBody] InsertEndpointAuthProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
var id = await mediator.ExecuteInsertProcedure(procedure, config["AddedWho"], cancel);
|
||||
return StatusCode(StatusCodes.Status201Created, id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an endpoint authentication record via the ENDPOINT_AUTH update procedure.
|
||||
/// </summary>
|
||||
/// <param name="id">ENDPOINT_AUTH identifier to update.</param>
|
||||
/// <param name="procedure">UpdateEndpointAuthProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpPut("{id:long}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Put([FromRoute] long id, [FromBody] UpdateEndpointAuthProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.ExecuteUpdateProcedure(procedure, id, cancel: cancel);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes endpoint authentication records via the ENDPOINT_AUTH delete procedure for the specified id range.
|
||||
/// </summary>
|
||||
/// <param name="procedure">DeleteEndpointAuthProcedure payload (Start, End, Force).</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpDelete]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Delete([FromBody] DeleteEndpointAuthProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.ExecuteDeleteProcedure(procedure, cancel);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
56
src/ReC.API/Controllers/EndpointParamsController.cs
Normal file
56
src/ReC.API/Controllers/EndpointParamsController.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.EndpointParams.Commands;
|
||||
|
||||
namespace ReC.API.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class EndpointParamsController(IMediator mediator, IConfiguration config) : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Inserts endpoint parameter records via the ENDPOINT_PARAMS insert procedure.
|
||||
/// </summary>
|
||||
/// <param name="procedure">InsertEndpointParamsProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The created ENDPOINT_PARAMS identifier.</returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||
public async Task<IActionResult> Post([FromBody] InsertEndpointParamsProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
var id = await mediator.ExecuteInsertProcedure(procedure, config["AddedWho"], cancel);
|
||||
return StatusCode(StatusCodes.Status201Created, id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates endpoint parameter records via the ENDPOINT_PARAMS update procedure.
|
||||
/// </summary>
|
||||
/// <param name="id">ENDPOINT_PARAMS identifier to update.</param>
|
||||
/// <param name="procedure">UpdateEndpointParamsProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpPut("{id:long}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Put([FromRoute] long id, [FromBody] UpdateEndpointParamsProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.ExecuteUpdateProcedure(procedure, id, cancel: cancel);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes endpoint parameter records via the ENDPOINT_PARAMS delete procedure for the specified id range.
|
||||
/// </summary>
|
||||
/// <param name="procedure">DeleteEndpointParamsProcedure payload (Start, End, Force).</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpDelete]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Delete([FromBody] DeleteEndpointParamsProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.ExecuteDeleteProcedure(procedure, cancel);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
56
src/ReC.API/Controllers/EndpointsController.cs
Normal file
56
src/ReC.API/Controllers/EndpointsController.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.Endpoints.Commands;
|
||||
|
||||
namespace ReC.API.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class EndpointsController(IMediator mediator, IConfiguration config) : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Inserts an endpoint via the ENDPOINT insert procedure.
|
||||
/// </summary>
|
||||
/// <param name="procedure">InsertEndpointProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The created ENDPOINT identifier.</returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||
public async Task<IActionResult> Post([FromBody] InsertEndpointProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
var id = await mediator.ExecuteInsertProcedure(procedure, config["AddedWho"], cancel);
|
||||
return StatusCode(StatusCodes.Status201Created, id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an endpoint via the ENDPOINT update procedure.
|
||||
/// </summary>
|
||||
/// <param name="id">ENDPOINT identifier to update.</param>
|
||||
/// <param name="procedure">UpdateEndpointProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpPut("{id:long}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Put([FromRoute] long id, [FromBody] UpdateEndpointProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.ExecuteUpdateProcedure(procedure, id, cancel: cancel);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes endpoints via the ENDPOINT delete procedure for the specified id range.
|
||||
/// </summary>
|
||||
/// <param name="procedure">DeleteEndpointProcedure payload (Start, End, Force).</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpDelete]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Delete([FromBody] DeleteEndpointProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.ExecuteDeleteProcedure(procedure, cancel);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ReC.API.Extensions;
|
||||
using ReC.API.Models;
|
||||
using ReC.Application.OutResults.Commands;
|
||||
using ReC.Application.OutResults.Queries;
|
||||
|
||||
namespace ReC.API.Controllers;
|
||||
|
||||
[Obsolete("This controller is deprecated and will be removed in future versions. Use the new ResultViewController instead.")]
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class OutResController(IMediator mediator, IConfiguration config) : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets output results based on the provided query parameters.
|
||||
/// </summary>
|
||||
/// <param name="query">The query to filter output results.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>A list of output results matching the query.</returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Get([FromQuery] ReadOutResQuery query, CancellationToken cancel) => Ok(await mediator.Send(query, cancel));
|
||||
|
||||
/// <summary>
|
||||
/// Gets output results for a fake/test profile.
|
||||
/// </summary>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>A list of output results for the fake profile.</returns>
|
||||
[HttpGet("fake")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public async Task<IActionResult> Get(CancellationToken cancel) => Ok(await mediator.Send(new ReadOutResQuery()
|
||||
{
|
||||
ProfileId = config.GetFakeProfileId()
|
||||
}, cancel));
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific output result for a fake/test profile and action.
|
||||
/// </summary>
|
||||
/// <param name="actionId">The ID of the action to retrieve the result for.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <param name="resultType">Specifies which part of the result to return (Full, OnlyHeader, or OnlyBody).</param>
|
||||
/// <returns>The requested output result or a part of it (header/body).</returns>
|
||||
[HttpGet("fake/{actionId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public async Task<IActionResult> Get([FromRoute] long actionId, CancellationToken cancel, ResultType resultType = ResultType.Full)
|
||||
{
|
||||
var res = (await mediator.Send(new ReadOutResQuery()
|
||||
{
|
||||
ProfileId = config.GetFakeProfileId(),
|
||||
ActionId = actionId
|
||||
}, cancel)).First();
|
||||
|
||||
return resultType switch
|
||||
{
|
||||
ResultType.OnlyBody => res.Body is null ? NotFound() : Ok(res.Body.JsonToDynamic()),
|
||||
ResultType.OnlyHeader => res.Header is null ? NotFound() : Ok(res.Header.JsonToDynamic()),
|
||||
_ => Ok(res),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes output results based on the provided criteria.
|
||||
/// </summary>
|
||||
/// <param name="command">The command containing the deletion criteria, such as ActionId or ProfileId.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>An empty response indicating success.</returns>
|
||||
[HttpDelete]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Delete([FromQuery] DeleteOutResCommand command, CancellationToken cancel)
|
||||
{
|
||||
await mediator.Send(command, cancel);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all output results for a fake/test profile.
|
||||
/// </summary>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>An empty response indicating success.</returns>
|
||||
[HttpDelete("fake")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> Delete(CancellationToken cancel)
|
||||
{
|
||||
await mediator.Send(new DeleteOutResCommand() { ProfileId = config.GetFakeProfileId() }, cancel);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
63
src/ReC.API/Controllers/ProfileController.cs
Normal file
63
src/ReC.API/Controllers/ProfileController.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.Profile.Commands;
|
||||
using ReC.Application.Profile.Queries;
|
||||
|
||||
namespace ReC.API.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ProfileController(IMediator mediator) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Get([FromQuery] ReadProfileViewQuery query, CancellationToken cancel)
|
||||
{
|
||||
return Ok(await mediator.Send(query, cancel));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a profile via the PROFILE insert procedure.
|
||||
/// </summary>
|
||||
/// <param name="procedure">InsertProfileProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The created profile identifier.</returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||
public async Task<IActionResult> Post([FromBody] InsertProfileProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
var id = await mediator.ExecuteInsertProcedure(procedure, cancel: cancel);
|
||||
return CreatedAtAction(nameof(Get), new { id }, id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a profile via the PROFILE update procedure.
|
||||
/// </summary>
|
||||
/// <param name="id">Profile identifier to update.</param>
|
||||
/// <param name="procedure">UpdateProfileProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpPut("{id:long}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Put([FromRoute] long id, [FromBody] UpdateProfileProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.ExecuteUpdateProcedure(procedure, id, cancel: cancel);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes profile records via the PROFILE delete procedure for the specified id range.
|
||||
/// </summary>
|
||||
/// <param name="procedure">DeleteProfileProcedure payload (Start, End, Force).</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpDelete]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Delete([FromBody] DeleteProfileProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.ExecuteDeleteProcedure(procedure, cancel);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ReC.API.Extensions;
|
||||
using ReC.API.Models;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.RecActions.Commands;
|
||||
using ReC.Application.RecActions.Queries;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ReC.API.Controllers;
|
||||
|
||||
@@ -26,19 +26,6 @@ public class RecActionController(IMediator mediator, IConfiguration config) : Co
|
||||
return Accepted();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a batch of RecActions for a fake/test profile.
|
||||
/// </summary>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>An HTTP 202 Accepted response indicating the process has been started.</returns>
|
||||
[HttpPost("invoke/fake")]
|
||||
[ProducesResponseType(StatusCodes.Status202Accepted)]
|
||||
public async Task<IActionResult> Invoke(CancellationToken cancel)
|
||||
{
|
||||
await mediator.InvokeBatchRecActionView(config.GetFakeProfileId(), cancel);
|
||||
return Accepted();
|
||||
}
|
||||
|
||||
#region CRUD
|
||||
/// <summary>
|
||||
/// Gets all RecActions for a given profile.
|
||||
@@ -50,20 +37,6 @@ public class RecActionController(IMediator mediator, IConfiguration config) : Co
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Get([FromQuery] ReadRecActionViewQuery query, CancellationToken cancel) => Ok(await mediator.Send(query, cancel));
|
||||
|
||||
/// <summary>
|
||||
/// Gets all RecActions for a fake/test profile.
|
||||
/// </summary>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <param name="invoked"></param>
|
||||
/// <returns>A list of RecActions for the fake profile.</returns>
|
||||
[HttpGet("fake")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Get(CancellationToken cancel, [FromQuery] bool invoked = false) => Ok(await mediator.Send(new ReadRecActionViewQuery()
|
||||
{
|
||||
ProfileId = config.GetFakeProfileId(),
|
||||
Invoked = invoked
|
||||
}, cancel));
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new RecAction.
|
||||
/// </summary>
|
||||
@@ -72,83 +45,39 @@ public class RecActionController(IMediator mediator, IConfiguration config) : Co
|
||||
/// <returns>An HTTP 201 Created response.</returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||
[Obsolete("Use the related procedure.")]
|
||||
public async Task<IActionResult> CreateAction([FromBody] CreateRecActionCommand command, CancellationToken cancel)
|
||||
public async Task<IActionResult> Create([FromBody] InsertActionProcedure command, CancellationToken cancel)
|
||||
{
|
||||
await mediator.Send(command, cancel);
|
||||
await mediator.ExecuteInsertProcedure(command, config["AddedWho"], cancel);
|
||||
|
||||
return CreatedAtAction(nameof(CreateAction), null);
|
||||
return StatusCode(StatusCodes.Status201Created);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new fake RecAction for testing purposes.
|
||||
/// Updates a RecAction via the ACTION update procedure.
|
||||
/// </summary>
|
||||
/// <param name="id">RecAction identifier to update.</param>
|
||||
/// <param name="procedure">UpdateActionProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <param name="request">The optional request body and header for the fake action.</param>
|
||||
/// <param name="endpointUri">The target endpoint URI.</param>
|
||||
/// <param name="endpointPath">The optional path to append to the endpoint URI.</param>
|
||||
/// <param name="type">The HTTP method type (e.g., GET, POST).</param>
|
||||
/// <returns>An HTTP 201 Created response.</returns>
|
||||
[HttpPost("fake")]
|
||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||
[Obsolete("Use the related procedure.")]
|
||||
public async Task<IActionResult> CreateFakeAction(
|
||||
CancellationToken cancel,
|
||||
[FromBody] FakeRequest? request = null,
|
||||
[FromQuery] string endpointUri = "https://jsonplaceholder.typicode.com/posts",
|
||||
[FromQuery] string? endpointPath = "1",
|
||||
[FromQuery] string type = "GET")
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpPut("{id:long}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Update([FromRoute] long id, [FromBody] UpdateActionProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
if (endpointPath is not null)
|
||||
endpointUri = new Uri(new Uri(endpointUri.TrimEnd('/') + "/"), endpointPath.TrimStart('/')).ToString();
|
||||
|
||||
var bodyJson = request?.Body is not null ? JsonSerializer.Serialize(request.Body, options: new() { WriteIndented = false }) : null;
|
||||
var headerJson = request?.Header is not null ? JsonSerializer.Serialize(request.Header, options: new() { WriteIndented = false }) : null;
|
||||
|
||||
await mediator.Send(new CreateRecActionCommand()
|
||||
{
|
||||
ProfileId = config.GetFakeProfileId(),
|
||||
EndpointUri = endpointUri,
|
||||
Type = type,
|
||||
BodyQuery = $@"SELECT '{bodyJson ?? "NULL"}' AS REQUEST_BODY;",
|
||||
HeaderQuery = headerJson is not null ? $@"SELECT '{headerJson}' AS REQUEST_HEADER;" : null,
|
||||
Active = true,
|
||||
EndpointAuthId = 4
|
||||
}, cancel);
|
||||
|
||||
return CreatedAtAction(nameof(CreateFakeAction), null);
|
||||
await mediator.ExecuteUpdateProcedure(procedure, id, cancel: cancel);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all RecActions associated with a specific profile.
|
||||
/// Deletes RecActions via the ACTION delete procedure for the specified id range.
|
||||
/// </summary>
|
||||
/// <param name="cmd"></param>
|
||||
/// <param name="procedure">DeleteActionProcedure payload (Start, End, Force).</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>An HTTP 204 No Content response upon successful deletion.</returns>
|
||||
[HttpDelete]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[Obsolete("Use the related procedure.")]
|
||||
public async Task<IActionResult> Delete([FromQuery] DeleteRecActionsCommand cmd, CancellationToken cancel)
|
||||
public async Task<IActionResult> Delete([FromBody] DeleteActionProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.Send(cmd, cancel);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all RecActions for a fake/test profile.
|
||||
/// </summary>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>An HTTP 204 No Content response upon successful deletion.</returns>
|
||||
[HttpDelete("fake")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[Obsolete("Use the related procedure.")]
|
||||
public async Task<IActionResult> Delete(CancellationToken cancel)
|
||||
{
|
||||
await mediator.Send(new DeleteRecActionsCommand()
|
||||
{
|
||||
ProfileId = config.GetFakeProfileId()
|
||||
}, cancel);
|
||||
|
||||
await mediator.ExecuteDeleteProcedure(procedure, cancel);
|
||||
return NoContent();
|
||||
}
|
||||
#endregion CRUD
|
||||
|
||||
69
src/ReC.API/Controllers/ResultController.cs
Normal file
69
src/ReC.API/Controllers/ResultController.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ReC.API.Extensions;
|
||||
using ReC.API.Models;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.Results.Commands;
|
||||
using ReC.Application.Results.Queries;
|
||||
|
||||
namespace ReC.API.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ResultController(IMediator mediator) : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets output results based on the provided query parameters.
|
||||
/// </summary>
|
||||
/// <param name="query">The query to filter output results.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>A list of output results matching the query.</returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Get([FromQuery] ReadResultViewQuery query, CancellationToken cancel) => Ok(await mediator.Send(query, cancel));
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a RESULT record via the insert procedure.
|
||||
/// </summary>
|
||||
/// <param name="procedure">InsertResultProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The created RESULT identifier.</returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||
public async Task<IActionResult> Post([FromBody] InsertResultProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
var id = await mediator.ExecuteInsertProcedure(procedure, cancel: cancel);
|
||||
return CreatedAtAction(nameof(Get), new { actionId = procedure.ActionId }, new { id, procedure.ActionId });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a RESULT record via the update procedure.
|
||||
/// </summary>
|
||||
/// <param name="id">RESULT identifier to update.</param>
|
||||
/// <param name="procedure">UpdateResultProcedure payload.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpPut("{id:long}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Put([FromRoute] long id, [FromBody] UpdateResultProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.ExecuteUpdateProcedure(procedure, id, cancel: cancel);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes RESULT records via the delete procedure for the specified id range.
|
||||
/// </summary>
|
||||
/// <param name="procedure">DeleteResultProcedure payload (Start, End, Force).</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>No content on success.</returns>
|
||||
[HttpDelete]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> Delete([FromBody] DeleteResultProcedure procedure, CancellationToken cancel)
|
||||
{
|
||||
await mediator.ExecuteDeleteProcedure(procedure, cancel);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ReC.API.Extensions;
|
||||
using ReC.API.Models;
|
||||
using ReC.Application.OutResults.Commands;
|
||||
using ReC.Application.OutResults.Queries;
|
||||
|
||||
namespace ReC.API.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ResultViewController(IMediator mediator, IConfiguration config) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Get([FromQuery] ReadResultViewQuery query, CancellationToken cancel) => Ok(await mediator.Send(query, cancel));
|
||||
|
||||
[HttpGet("fake")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Get(CancellationToken cancel) => Ok(await mediator.Send(new ReadResultViewQuery()
|
||||
{
|
||||
ProfileId = config.GetFakeProfileId()
|
||||
}, cancel));
|
||||
|
||||
[HttpGet("fake/{actionId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Get([FromRoute] long actionId, CancellationToken cancel, ResultType resultType = ResultType.Full)
|
||||
{
|
||||
var res = (await mediator.Send(new ReadResultViewQuery()
|
||||
{
|
||||
ProfileId = config.GetFakeProfileId(),
|
||||
ActionId = actionId
|
||||
}, cancel)).First();
|
||||
|
||||
return resultType switch
|
||||
{
|
||||
ResultType.OnlyBody => res.Body is null ? NotFound() : Ok(res.Body.JsonToDynamic()),
|
||||
ResultType.OnlyHeader => res.Header is null ? NotFound() : Ok(res.Header.JsonToDynamic()),
|
||||
_ => Ok(res),
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create([FromBody] CreateResultViewCommand command, CancellationToken cancel)
|
||||
{
|
||||
await mediator.Send(command, cancel);
|
||||
return CreatedAtAction(nameof(Get), new { actionId = command.ActionId }, command);
|
||||
}
|
||||
}
|
||||
@@ -63,10 +63,17 @@ public class ExceptionHandlingMiddleware
|
||||
switch (exception)
|
||||
{
|
||||
case BadRequestException badRequestEx:
|
||||
if (badRequestEx.InnerException is not null)
|
||||
{
|
||||
logger.LogError(
|
||||
badRequestEx.InnerException,
|
||||
"BadRequestException inner exception captured.");
|
||||
}
|
||||
|
||||
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||
details = new()
|
||||
{
|
||||
Title = "Bad Request",
|
||||
Title = "Bad Procedure",
|
||||
Detail = badRequestEx.Message
|
||||
};
|
||||
break;
|
||||
@@ -106,6 +113,57 @@ public class ExceptionHandlingMiddleware
|
||||
};
|
||||
break;
|
||||
|
||||
case InsertObjectFailedException insertFailedEx:
|
||||
logger.LogError(
|
||||
insertFailedEx,
|
||||
"Insert operation failed during request processing. {procedure}",
|
||||
JsonSerializer.Serialize(
|
||||
insertFailedEx.Procedure,
|
||||
options: new() { WriteIndented = true }
|
||||
));
|
||||
|
||||
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
||||
details = new()
|
||||
{
|
||||
Title = "Insert Operation Failed",
|
||||
Detail = insertFailedEx.Message
|
||||
};
|
||||
break;
|
||||
|
||||
case UpdateObjectFailedException updateFailedEx:
|
||||
logger.LogError(
|
||||
updateFailedEx,
|
||||
"Update operation failed during request processing. {procedure}",
|
||||
JsonSerializer.Serialize(
|
||||
updateFailedEx.Procedure,
|
||||
options: new() { WriteIndented = true }
|
||||
));
|
||||
|
||||
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
||||
details = new()
|
||||
{
|
||||
Title = "Update Operation Failed",
|
||||
Detail = updateFailedEx.Message
|
||||
};
|
||||
break;
|
||||
|
||||
case DeleteObjectFailedException deleteFailedEx:
|
||||
logger.LogError(
|
||||
deleteFailedEx,
|
||||
"Delete operation failed during request processing. {procedure}",
|
||||
JsonSerializer.Serialize(
|
||||
deleteFailedEx.Procedure,
|
||||
options: new() { WriteIndented = true }
|
||||
));
|
||||
|
||||
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
||||
details = new()
|
||||
{
|
||||
Title = "Delete Operation Failed",
|
||||
Detail = deleteFailedEx.Message
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
logger.LogError(exception, "Unhandled exception occurred.");
|
||||
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
||||
@@ -120,4 +178,4 @@ public class ExceptionHandlingMiddleware
|
||||
if (details is not null)
|
||||
await context.Response.WriteAsJsonAsync(details);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ try
|
||||
{
|
||||
options.LuckyPennySoftwareLicenseKey = builder.Configuration["LuckyPennySoftwareLicenseKey"];
|
||||
options.ConfigureRecActions(config.GetSection("RecAction"));
|
||||
options.ConfigureSqlException(config.GetSection("SqlException"));
|
||||
});
|
||||
|
||||
builder.Services.AddRecInfrastructure(options =>
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
<Product>ReC.API</Product>
|
||||
<PackageIcon>Assets\icon.ico</PackageIcon>
|
||||
<PackageTags>digital data rest-caller rec api</PackageTags>
|
||||
<Version>1.0.3-beta</Version>
|
||||
<AssemblyVersion>1.0.3.0</AssemblyVersion>
|
||||
<FileVersion>1.0.3.0</FileVersion>
|
||||
<InformationalVersion>1.0.3-beta</InformationalVersion>
|
||||
<Version>2.0.0-beta</Version>
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
<FileVersion>2.0.0.0</FileVersion>
|
||||
<InformationalVersion>2.0.0-beta</InformationalVersion>
|
||||
<Copyright>Copyright © 2025 Digital Data GmbH. All rights reserved.</Copyright>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
"RecAction": {
|
||||
"MaxConcurrentInvocations": 5
|
||||
},
|
||||
// Bad request SqlException numbers numbers can be updated at runtime; no restart required.
|
||||
"SqlException": {
|
||||
// https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlexception.number
|
||||
"BadRequestSqlExceptionNumbers": [ 515, 547, 2601, 2627, 50000 ]
|
||||
},
|
||||
"AddedWho": "ReC.API",
|
||||
"FakeProfileId": 2
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,5 +1,4 @@
|
||||
using ReC.Domain.Entities;
|
||||
using ReC.Domain.Views;
|
||||
using ReC.Domain.Views;
|
||||
|
||||
namespace ReC.Application.Common.Dto;
|
||||
|
||||
@@ -8,16 +7,6 @@ public class DtoMappingProfile : AutoMapper.Profile
|
||||
public DtoMappingProfile()
|
||||
{
|
||||
CreateMap<RecActionView, RecActionViewDto>();
|
||||
CreateMap<OutRes, OutResDto>();
|
||||
|
||||
|
||||
CreateMap<Connection, ConnectionDto>();
|
||||
CreateMap<EndpointAuth, EndpointAuthDto>();
|
||||
CreateMap<Endpoint, EndpointDto>();
|
||||
CreateMap<EndpointParam, EndpointParamDto>();
|
||||
CreateMap<Profile, ProfileDto>();
|
||||
CreateMap<RecAction, RecActionDto>();
|
||||
|
||||
CreateMap<ResultView, ResultViewDto>();
|
||||
CreateMap<ProfileView, ProfileViewDto>();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Application.Common.Dto;
|
||||
|
||||
[Table("TBREC_CFG_ENDPOINT_AUTH")]
|
||||
public record EndpointAuthDto
|
||||
{
|
||||
public long? Id { get; set; }
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace ReC.Application.Common.Dto;
|
||||
|
||||
[Table("TBREC_CFG_PROFILE", Schema = "dbo")]
|
||||
public record ProfileDto
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Application.Common.Dto;
|
||||
|
||||
[Table("TBREC_CFG_ACTION")]
|
||||
public record RecActionDto
|
||||
{
|
||||
public long? Id { get; set; }
|
||||
|
||||
@@ -20,7 +20,7 @@ public record RecActionViewDto
|
||||
|
||||
public long? EndpointAuthId { get; init; }
|
||||
|
||||
public EndpointAuthType? EndpointAuthType { get; init; }
|
||||
public EndpointAuthType EndpointAuthType { get; init; } = EndpointAuthType.NoAuth;
|
||||
|
||||
public string? EndpointAuthTypeName { get; init; }
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
|
||||
namespace ReC.Application.Common.Exceptions;
|
||||
|
||||
public class DeleteObjectFailedException : Exception
|
||||
{
|
||||
public DeleteObjectProcedure Procedure { get; }
|
||||
|
||||
public DeleteObjectFailedException(DeleteObjectProcedure procedure) : base()
|
||||
{
|
||||
Procedure = procedure;
|
||||
}
|
||||
|
||||
public DeleteObjectFailedException(DeleteObjectProcedure procedure, string? message) : base(message)
|
||||
{
|
||||
Procedure = procedure;
|
||||
}
|
||||
|
||||
public DeleteObjectFailedException(DeleteObjectProcedure procedure, string? message, Exception? innerException) : base(message, innerException)
|
||||
{
|
||||
Procedure = procedure;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
|
||||
namespace ReC.Application.Common.Exceptions;
|
||||
|
||||
public class InsertObjectFailedException : Exception
|
||||
{
|
||||
public InsertObjectProcedure Procedure { get; }
|
||||
|
||||
public InsertObjectFailedException(InsertObjectProcedure procedure) : base()
|
||||
{
|
||||
Procedure = procedure;
|
||||
}
|
||||
|
||||
public InsertObjectFailedException(InsertObjectProcedure procedure, string? message) : base(message)
|
||||
{
|
||||
Procedure = procedure;
|
||||
}
|
||||
|
||||
public InsertObjectFailedException(InsertObjectProcedure procedure, string? message, Exception? innerException) : base(message, innerException)
|
||||
{
|
||||
Procedure = procedure;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
|
||||
namespace ReC.Application.Common.Exceptions;
|
||||
|
||||
public class UpdateObjectFailedException : Exception
|
||||
{
|
||||
public UpdateObjectProcedure Procedure { get; }
|
||||
|
||||
public UpdateObjectFailedException(UpdateObjectProcedure procedure) : base()
|
||||
{
|
||||
Procedure = procedure;
|
||||
}
|
||||
|
||||
public UpdateObjectFailedException(UpdateObjectProcedure procedure, string? message) : base(message)
|
||||
{
|
||||
Procedure = procedure;
|
||||
}
|
||||
|
||||
public UpdateObjectFailedException(UpdateObjectProcedure procedure, string? message, Exception? innerException) : base(message, innerException)
|
||||
{
|
||||
Procedure = procedure;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,24 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ReC.Domain.Entities;
|
||||
using ReC.Domain.QueryOutput;
|
||||
using ReC.Domain.Views;
|
||||
|
||||
namespace ReC.Application.Common.Interfaces;
|
||||
|
||||
public interface IRecDbContext
|
||||
{
|
||||
public DbSet<EndpointParam> EndpointParams { get; set; }
|
||||
|
||||
#region DbSets
|
||||
public DbSet<RecActionView> RecActionViews { get; set; }
|
||||
|
||||
public DbSet<OutRes> OutRes { get; set; }
|
||||
public DbSet<ProfileView> ProfileViews { get; set; }
|
||||
|
||||
public DbSet<ResultView> RecResultViews { get; set; }
|
||||
|
||||
public DbSet<HeaderQueryResult> HeaderQueryResults { get; set; }
|
||||
|
||||
public DbSet<BodyQueryResult> BodyQueryResults { get; set; }
|
||||
|
||||
public DbSet<Connection> Connections { get; set; }
|
||||
|
||||
public DbSet<Endpoint> Endpoints { get; set; }
|
||||
|
||||
public DbSet<EndpointAuth> EndpointAuths { get; set; }
|
||||
|
||||
public DbSet<Profile> Profiles { get; set; }
|
||||
|
||||
public DbSet<RecAction> RecActions { get; set; }
|
||||
public DbSet<InsertObjectResult> RecResults { get; set; }
|
||||
#endregion DbSets
|
||||
|
||||
public Task<int> SaveChangesAsync(CancellationToken cancel = default);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ReC.Application.Common.Options;
|
||||
|
||||
public class SqlExceptionOptions
|
||||
{
|
||||
public HashSet<int> BadRequestSqlExceptionNumbers { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using MediatR;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ReC.Application.Common.Exceptions;
|
||||
using ReC.Application.Common.Options;
|
||||
|
||||
namespace ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
|
||||
public record DeleteObjectProcedure : IRequest<int>
|
||||
{
|
||||
/// <summary>
|
||||
/// Target entity: ACTION, ENDPOINT, ENDPOINT_AUTH, ENDPOINT_PARAMS, PROFILE, RESULT
|
||||
/// </summary>
|
||||
public string Entity { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Start GUID/ID (inclusive)
|
||||
/// </summary>
|
||||
public long Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// End GUID/ID (inclusive). If 0, will be set to Start value.
|
||||
/// </summary>
|
||||
public long End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, delete even if dependent data exists
|
||||
/// </summary>
|
||||
public bool Force { get; set; }
|
||||
}
|
||||
|
||||
public static class DeleteObjectProcedureExtensions
|
||||
{
|
||||
public static Task<int> ExecuteDeleteProcedure(this ISender sender, IDeleteProcedure procedure, CancellationToken cancel = default)
|
||||
{
|
||||
return sender.Send(procedure.ToObjectProcedure(), cancel);
|
||||
}
|
||||
|
||||
public static Task<int> ExecuteDeleteProcedure(this ISender sender, string entity, long start, long end = 0, bool force = false, CancellationToken cancel = default)
|
||||
{
|
||||
return sender.Send(new DeleteObjectProcedure
|
||||
{
|
||||
Entity = entity,
|
||||
Start = start,
|
||||
End = end,
|
||||
Force = force
|
||||
}, cancel);
|
||||
}
|
||||
}
|
||||
|
||||
public class DeleteObjectProcedureHandler(IRepository repo, IOptionsMonitor<SqlExceptionOptions> sqlExOpt) : IRequestHandler<DeleteObjectProcedure, int>
|
||||
{
|
||||
public async Task<int> Handle(DeleteObjectProcedure request, CancellationToken cancel)
|
||||
{
|
||||
var parameters = new[]
|
||||
{
|
||||
new SqlParameter("@pENTITY", request.Entity ?? (object)DBNull.Value),
|
||||
new SqlParameter("@pSTART", request.Start.ToString()),
|
||||
new SqlParameter("@pEND", request.End.ToString()),
|
||||
new SqlParameter("@pFORCE", (object?)request.Force ?? DBNull.Value)
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var result = await repo.ExecuteQueryRawAsync(
|
||||
"DECLARE @RC SMALLINT = 0; " +
|
||||
"EXEC @RC = [dbo].[PRREC_DELETE_OBJECT] " +
|
||||
"@pENTITY, @pSTART, @pEND, @pFORCE; " +
|
||||
"SELECT @RC;",
|
||||
parameters,
|
||||
cancel);
|
||||
|
||||
// The stored procedure returns 0 on success, error codes > 0 on failure
|
||||
if (result > 0)
|
||||
{
|
||||
throw new DeleteObjectFailedException(request, $"DeleteObject stored procedure failed with error code: {result}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
if (sqlExOpt.CurrentValue.BadRequestSqlExceptionNumbers.Contains(ex.Number))
|
||||
throw new BadRequestException(ex.Message, ex);
|
||||
else
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
|
||||
public interface IDeleteProcedure
|
||||
{
|
||||
public DeleteObjectProcedure ToObjectProcedure();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ReC.Application.Common.Procedures.InsertProcedure;
|
||||
|
||||
public interface IInsertProcedure
|
||||
{
|
||||
public InsertObjectProcedure ToObjectProcedure(string? addedWho = null);
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using MediatR;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ReC.Application.Common.Exceptions;
|
||||
using ReC.Application.Common.Options;
|
||||
using ReC.Application.EndpointAuth.Commands;
|
||||
using ReC.Application.EndpointParams.Commands;
|
||||
using ReC.Application.Endpoints.Commands;
|
||||
using ReC.Application.Profile.Commands;
|
||||
using ReC.Application.RecActions.Commands;
|
||||
using ReC.Application.Results.Commands;
|
||||
|
||||
namespace ReC.Application.Common.Procedures.InsertProcedure;
|
||||
|
||||
public record InsertObjectProcedure : IRequest<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// Target entity: ACTION, ENDPOINT, ENDPOINT_AUTH, ENDPOINT_PARAMS, PROFILE, RESULT
|
||||
/// </summary>
|
||||
public string Entity { get; set; } = null!;
|
||||
|
||||
internal string? AddedWho { get; private set; }
|
||||
|
||||
public InsertObjectProcedure AddedBy(string? addedWho = null)
|
||||
{
|
||||
AddedWho = addedWho ?? "ReC.API";
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertActionProcedure Action { get; set; } = new();
|
||||
public InsertEndpointProcedure Endpoint { get; set; } = new();
|
||||
public InsertEndpointAuthProcedure EndpointAuth { get; set; } = new();
|
||||
public InsertProfileProcedure Profile { get; set; } = new();
|
||||
public InsertResultProcedure Result { get; set; } = new();
|
||||
public InsertEndpointParamsProcedure EndpointParams { get; set; } = new();
|
||||
}
|
||||
|
||||
public static class InsertObjectProcedureExtensions
|
||||
{
|
||||
public static Task<long> ExecuteInsertProcedure(this ISender sender, IInsertProcedure procedure, string? addedWho = null, CancellationToken cancel = default)
|
||||
{
|
||||
return sender.Send(procedure.ToObjectProcedure(addedWho ?? "Rec.API"), cancel);
|
||||
}
|
||||
}
|
||||
|
||||
public class InsertObjectProcedureHandler(IRepository repo, IOptionsMonitor<SqlExceptionOptions> sqlExOpt) : IRequestHandler<InsertObjectProcedure, long>
|
||||
{
|
||||
public async Task<long> Handle(InsertObjectProcedure request, CancellationToken cancel)
|
||||
{
|
||||
var parameters = new[]
|
||||
{
|
||||
new SqlParameter("@pENTITY", request.Entity ?? (object)DBNull.Value),
|
||||
|
||||
new SqlParameter("@pADDED_WHO", (object?)request.AddedWho ?? DBNull.Value),
|
||||
new SqlParameter("@pADDED_WHEN", (object?)DateTime.UtcNow ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pACTION_PROFILE_ID", (object?)request.Action.ProfileId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_ACTIVE", (object?)request.Action.Active ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_SEQUENCE", (object?)request.Action.Sequence ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_ENDPOINT_ID", (object?)request.Action.EndpointId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_ENDPOINT_AUTH_ID", (object?)request.Action.EndpointAuthId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_ENDPOINT_PARAMS_ID", (object?)request.Action.EndpointParamsId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_SQL_CONNECTION_ID", (object?)request.Action.SqlConnectionId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_TYPE_ID", (object?)(byte?)request.Action.TypeId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_PRE_SQL", (object?)request.Action.PreSql ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_HEADER_SQL", (object?)request.Action.HeaderSql ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_BODY_SQL", (object?)request.Action.BodySql ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_POST_SQL", (object?)request.Action.PostSql ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_ERROR_ACTION_ID", (object?)request.Action.ErrorActionId ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pENDPOINT_ACTIVE", (object?)request.Endpoint.Active ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_DESCRIPTION", (object?)request.Endpoint.Description ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_URI", (object?)request.Endpoint.Uri ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pENDPOINT_AUTH_ACTIVE", (object?)request.EndpointAuth.Active ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_DESCRIPTION", (object?)request.EndpointAuth.Description ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_TYPE_ID", (object?)request.EndpointAuth.TypeId ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_API_KEY", (object?)request.EndpointAuth.ApiKey ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_API_VALUE", (object?)request.EndpointAuth.ApiValue ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_API_KEY_ADD_TO_ID", (object?)request.EndpointAuth.ApiKeyAddToId ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_TOKEN", (object?)request.EndpointAuth.Token ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_USERNAME", (object?)request.EndpointAuth.Username ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_PASSWORD", (object?)request.EndpointAuth.Password ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_DOMAIN", (object?)request.EndpointAuth.Domain ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_WORKSTATION", (object?)request.EndpointAuth.Workstation ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pPROFILE_ACTIVE", (object?)request.Profile.Active ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_TYPE_ID", (object?)request.Profile.TypeId ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_MANDANTOR", (object?)request.Profile.Mandantor ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_NAME", (object?)request.Profile.Name ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_DESCRIPTION", (object?)request.Profile.Description ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_LOG_LEVEL_ID", (object?)request.Profile.LogLevelId ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_LANGUAGE_ID", (object?)request.Profile.LanguageId ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pRESULT_ACTION_ID", (object?)request.Result.ActionId ?? DBNull.Value),
|
||||
new SqlParameter("@pRESULT_STATUS_ID", (object?)request.Result.StatusId ?? DBNull.Value),
|
||||
new SqlParameter("@pRESULT_HEADER", (object?)request.Result.Header ?? DBNull.Value),
|
||||
new SqlParameter("@pRESULT_BODY", (object?)request.Result.Body ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pENDPOINT_PARAMS_ACTIVE", (object?)request.EndpointParams.Active ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_PARAMS_DESCRIPTION", (object?)request.EndpointParams.Description ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_PARAMS_GROUP_ID", (object?)request.EndpointParams.GroupId ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_PARAMS_SEQUENCE", (object?)request.EndpointParams.Sequence ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_PARAMS_KEY", (object?)request.EndpointParams.Key ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_PARAMS_VALUE", (object?)request.EndpointParams.Value ?? DBNull.Value),
|
||||
|
||||
new SqlParameter
|
||||
{
|
||||
ParameterName = "@oGUID",
|
||||
SqlDbType = System.Data.SqlDbType.BigInt,
|
||||
Direction = System.Data.ParameterDirection.Output
|
||||
}
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
await repo.ExecuteQueryRawAsync(
|
||||
"EXEC [dbo].[PRREC_INSERT_OBJECT] " +
|
||||
"@pENTITY, @pADDED_WHO, @pADDED_WHEN, " +
|
||||
"@pACTION_PROFILE_ID, @pACTION_ACTIVE, @pACTION_SEQUENCE, @pACTION_ENDPOINT_ID, @pACTION_ENDPOINT_AUTH_ID, @pACTION_ENDPOINT_PARAMS_ID, @pACTION_SQL_CONNECTION_ID, @pACTION_TYPE_ID, @pACTION_PRE_SQL, @pACTION_HEADER_SQL, @pACTION_BODY_SQL, @pACTION_POST_SQL, @pACTION_ERROR_ACTION_ID, " +
|
||||
"@pENDPOINT_ACTIVE, @pENDPOINT_DESCRIPTION, @pENDPOINT_URI, " +
|
||||
"@pENDPOINT_AUTH_ACTIVE, @pENDPOINT_AUTH_DESCRIPTION, @pENDPOINT_AUTH_TYPE_ID, @pENDPOINT_AUTH_API_KEY, @pENDPOINT_AUTH_API_VALUE, @pENDPOINT_AUTH_API_KEY_ADD_TO_ID, @pENDPOINT_AUTH_TOKEN, @pENDPOINT_AUTH_USERNAME, @pENDPOINT_AUTH_PASSWORD, @pENDPOINT_AUTH_DOMAIN, @pENDPOINT_AUTH_WORKSTATION, " +
|
||||
"@pPROFILE_ACTIVE, @pPROFILE_TYPE_ID, @pPROFILE_MANDANTOR, @pPROFILE_NAME, @pPROFILE_DESCRIPTION, @pPROFILE_LOG_LEVEL_ID, @pPROFILE_LANGUAGE_ID, " +
|
||||
"@pRESULT_ACTION_ID, @pRESULT_STATUS_ID, @pRESULT_HEADER, @pRESULT_BODY, " +
|
||||
"@pENDPOINT_PARAMS_ACTIVE, @pENDPOINT_PARAMS_DESCRIPTION, @pENDPOINT_PARAMS_GROUP_ID, @pENDPOINT_PARAMS_SEQUENCE, @pENDPOINT_PARAMS_KEY, @pENDPOINT_PARAMS_VALUE, " +
|
||||
"@oGUID OUTPUT",
|
||||
parameters,
|
||||
cancel);
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
if (sqlExOpt.CurrentValue.BadRequestSqlExceptionNumbers.Contains(ex.Number))
|
||||
throw new BadRequestException(ex.Message, ex);
|
||||
else
|
||||
throw;
|
||||
}
|
||||
|
||||
var guidParam = parameters.Last();
|
||||
|
||||
if (guidParam.Value != DBNull.Value)
|
||||
if (guidParam.Value is long longValue)
|
||||
return longValue;
|
||||
else if (long.TryParse(guidParam.Value.ToString(), out var guid))
|
||||
return guid;
|
||||
|
||||
throw new InsertObjectFailedException(request, "InsertObject stored procedure did not return a valid identifier.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
|
||||
public interface IUpdateProcedure
|
||||
{
|
||||
public UpdateObjectProcedure ToObjectProcedure(long id, string? changedWho = null);
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using MediatR;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ReC.Application.Common.Exceptions;
|
||||
using ReC.Application.Common.Options;
|
||||
using ReC.Application.EndpointAuth.Commands;
|
||||
using ReC.Application.EndpointParams.Commands;
|
||||
using ReC.Application.Endpoints.Commands;
|
||||
using ReC.Application.Profile.Commands;
|
||||
using ReC.Application.RecActions.Commands;
|
||||
using ReC.Application.Results.Commands;
|
||||
|
||||
namespace ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
|
||||
public record UpdateObjectProcedure : IRequest<int>
|
||||
{
|
||||
/// <summary>
|
||||
/// Target entity: ACTION, ENDPOINT, ENDPOINT_AUTH, ENDPOINT_PARAMS, PROFILE, RESULT
|
||||
/// </summary>
|
||||
public string Entity { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Target GUID to update (required)
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
internal string? ChangedWho { get; private set; }
|
||||
|
||||
public UpdateObjectProcedure ChangedBy(string? changedWho = null)
|
||||
{
|
||||
ChangedWho = changedWho ?? "ReC.API";
|
||||
return this;
|
||||
}
|
||||
|
||||
public UpdateActionProcedure Action { get; set; } = new();
|
||||
public UpdateEndpointProcedure Endpoint { get; set; } = new();
|
||||
public UpdateEndpointAuthProcedure EndpointAuth { get; set; } = new();
|
||||
public UpdateProfileProcedure Profile { get; set; } = new();
|
||||
public UpdateResultProcedure Result { get; set; } = new();
|
||||
public UpdateEndpointParamsProcedure EndpointParams { get; set; } = new();
|
||||
}
|
||||
|
||||
public static class UpdateObjectProcedureExtensions
|
||||
{
|
||||
public static Task<int> ExecuteUpdateProcedure(this ISender sender, IUpdateProcedure procedure, long id, string? changedWho = null, CancellationToken cancel = default)
|
||||
{
|
||||
return sender.Send(procedure.ToObjectProcedure(id, changedWho ?? "ReC.API"), cancel);
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateObjectProcedureHandler(IRepository repo, IOptionsMonitor<SqlExceptionOptions> sqlExOpt) : IRequestHandler<UpdateObjectProcedure, int>
|
||||
{
|
||||
public async Task<int> Handle(UpdateObjectProcedure request, CancellationToken cancel)
|
||||
{
|
||||
var parameters = new[]
|
||||
{
|
||||
new SqlParameter("@pENTITY", request.Entity ?? (object)DBNull.Value),
|
||||
new SqlParameter("@pGUID", (object?)request.Id ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pCHANGED_WHO", (object?)request.ChangedWho ?? DBNull.Value),
|
||||
new SqlParameter("@pCHANGED_WHEN", (object?)DateTime.UtcNow ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pACTION_PROFILE_ID", (object?)request.Action.ProfileId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_ACTIVE", (object?)request.Action.Active ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_SEQUENCE", (object?)request.Action.Sequence ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_ENDPOINT_ID", (object?)request.Action.EndpointId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_ENDPOINT_AUTH_ID", (object?)request.Action.EndpointAuthId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_ENDPOINT_PARAMS_ID", (object?)request.Action.EndpointParamsId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_SQL_CONNECTION_ID", (object?)request.Action.SqlConnectionId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_TYPE_ID", (object?)request.Action.TypeId ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_PRE_SQL", (object?)request.Action.PreSql ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_HEADER_SQL", (object?)request.Action.HeaderSql ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_BODY_SQL", (object?)request.Action.BodySql ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_POST_SQL", (object?)request.Action.PostSql ?? DBNull.Value),
|
||||
new SqlParameter("@pACTION_ERROR_ACTION_ID", (object?)request.Action.ErrorActionId ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pENDPOINT_ACTIVE", (object?)request.Endpoint.Active ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_DESCRIPTION", (object?)request.Endpoint.Description ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_URI", (object?)request.Endpoint.Uri ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pENDPOINT_AUTH_ACTIVE", (object?)request.EndpointAuth.Active ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_DESCRIPTION", (object?)request.EndpointAuth.Description ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_TYPE_ID", (object?)request.EndpointAuth.TypeId ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_API_KEY", (object?)request.EndpointAuth.ApiKey ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_API_VALUE", (object?)request.EndpointAuth.ApiValue ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_API_KEY_ADD_TO_ID", (object?)request.EndpointAuth.ApiKeyAddToId ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_TOKEN", (object?)request.EndpointAuth.Token ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_USERNAME", (object?)request.EndpointAuth.Username ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_PASSWORD", (object?)request.EndpointAuth.Password ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_DOMAIN", (object?)request.EndpointAuth.Domain ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_AUTH_WORKSTATION", (object?)request.EndpointAuth.Workstation ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pENDPOINT_PARAMS_ACTIVE", (object?)request.EndpointParams.Active ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_PARAMS_DESCRIPTION", (object?)request.EndpointParams.Description ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_PARAMS_GROUP_ID", (object?)request.EndpointParams.GroupId ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_PARAMS_SEQUENCE", (object?)request.EndpointParams.Sequence ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_PARAMS_KEY", (object?)request.EndpointParams.Key ?? DBNull.Value),
|
||||
new SqlParameter("@pENDPOINT_PARAMS_VALUE", (object?)request.EndpointParams.Value ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pPROFILE_ACTIVE", (object?)request.Profile.Active ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_TYPE_ID", (object?)request.Profile.TypeId ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_MANDANTOR", (object?)request.Profile.Mandantor ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_NAME", (object?)request.Profile.Name ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_DESCRIPTION", (object?)request.Profile.Description ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_LOG_LEVEL_ID", (object?)request.Profile.LogLevelId ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_LANGUAGE_ID", (object?)request.Profile.LanguageId ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_FIRST_RUN", (object?)request.Profile.FirstRun ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_LAST_RUN", (object?)request.Profile.LastRun ?? DBNull.Value),
|
||||
new SqlParameter("@pPROFILE_LAST_RESULT", (object?)request.Profile.LastResult ?? DBNull.Value),
|
||||
|
||||
new SqlParameter("@pRESULT_ACTION_ID", (object?)request.Result.ActionId ?? DBNull.Value),
|
||||
new SqlParameter("@pRESULT_STATUS_ID", (object?)request.Result.StatusId ?? DBNull.Value),
|
||||
new SqlParameter("@pRESULT_HEADER", (object?)request.Result.Header ?? DBNull.Value),
|
||||
new SqlParameter("@pRESULT_BODY", (object?)request.Result.Body ?? DBNull.Value)
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var result = await repo.ExecuteQueryRawAsync(
|
||||
"DECLARE @RC SMALLINT = 0; " +
|
||||
"EXEC @RC = [dbo].[PRREC_UPDATE_OBJECT] " +
|
||||
"@pENTITY, @pGUID, @pCHANGED_WHO, @pCHANGED_WHEN, " +
|
||||
"@pACTION_PROFILE_ID, @pACTION_ACTIVE, @pACTION_SEQUENCE, @pACTION_ENDPOINT_ID, @pACTION_ENDPOINT_AUTH_ID, @pACTION_ENDPOINT_PARAMS_ID, @pACTION_SQL_CONNECTION_ID, @pACTION_TYPE_ID, @pACTION_PRE_SQL, @pACTION_HEADER_SQL, @pACTION_BODY_SQL, @pACTION_POST_SQL, @pACTION_ERROR_ACTION_ID, " +
|
||||
"@pENDPOINT_ACTIVE, @pENDPOINT_DESCRIPTION, @pENDPOINT_URI, " +
|
||||
"@pENDPOINT_AUTH_ACTIVE, @pENDPOINT_AUTH_DESCRIPTION, @pENDPOINT_AUTH_TYPE_ID, @pENDPOINT_AUTH_API_KEY, @pENDPOINT_AUTH_API_VALUE, @pENDPOINT_AUTH_API_KEY_ADD_TO_ID, @pENDPOINT_AUTH_TOKEN, @pENDPOINT_AUTH_USERNAME, @pENDPOINT_AUTH_PASSWORD, @pENDPOINT_AUTH_DOMAIN, @pENDPOINT_AUTH_WORKSTATION, " +
|
||||
"@pENDPOINT_PARAMS_ACTIVE, @pENDPOINT_PARAMS_DESCRIPTION, @pENDPOINT_PARAMS_GROUP_ID, @pENDPOINT_PARAMS_SEQUENCE, @pENDPOINT_PARAMS_KEY, @pENDPOINT_PARAMS_VALUE, " +
|
||||
"@pPROFILE_ACTIVE, @pPROFILE_TYPE_ID, @pPROFILE_MANDANTOR, @pPROFILE_NAME, @pPROFILE_DESCRIPTION, @pPROFILE_LOG_LEVEL_ID, @pPROFILE_LANGUAGE_ID, @pPROFILE_FIRST_RUN, @pPROFILE_LAST_RUN, @pPROFILE_LAST_RESULT, " +
|
||||
"@pRESULT_ACTION_ID, @pRESULT_STATUS_ID, @pRESULT_HEADER, @pRESULT_BODY; " +
|
||||
"SELECT @RC;",
|
||||
parameters,
|
||||
cancel);
|
||||
|
||||
// The stored procedure returns 0 on success, error codes > 0 on failure
|
||||
if (result > 0)
|
||||
{
|
||||
throw new UpdateObjectFailedException(request, $"UpdateObject stored procedure failed with error code: {result}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
if (sqlExOpt.CurrentValue.BadRequestSqlExceptionNumbers.Contains(ex.Number))
|
||||
throw new BadRequestException(ex.Message, ex);
|
||||
else
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using FluentValidation;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
|
||||
namespace ReC.Application.Common.Validations;
|
||||
|
||||
public class InsertObjectProcedureValidator : AbstractValidator<InsertObjectProcedure>
|
||||
{
|
||||
public InsertObjectProcedureValidator()
|
||||
{
|
||||
// ENTITY must be one of the allowed values
|
||||
RuleFor(x => x.Entity)
|
||||
.NotEmpty()
|
||||
.Must(e => e is "ACTION" or "ENDPOINT" or "ENDPOINT_AUTH" or "ENDPOINT_PARAMS" or "PROFILE" or "RESULT")
|
||||
.WithMessage("ENTITY must be one of: ACTION, ENDPOINT, ENDPOINT_AUTH, ENDPOINT_PARAMS, PROFILE, RESULT.");
|
||||
|
||||
// ACTION validation
|
||||
When(x => x.Entity == "ACTION", () =>
|
||||
{
|
||||
RuleFor(x => x.Action.ProfileId)
|
||||
.NotNull()
|
||||
.WithMessage("ACTION requires ActionProfileId (maps to @pACTION_PROFILE_ID).");
|
||||
|
||||
RuleFor(x => x.Action.EndpointId)
|
||||
.NotNull()
|
||||
.WithMessage("ACTION requires ActionEndpointId (maps to @pACTION_ENDPOINT_ID).");
|
||||
});
|
||||
|
||||
// ENDPOINT validation
|
||||
When(x => x.Entity == "ENDPOINT", () =>
|
||||
{
|
||||
RuleFor(x => x.Endpoint.Uri)
|
||||
.NotEmpty()
|
||||
.WithMessage("ENDPOINT requires EndpointUri (maps to @pENDPOINT_URI).")
|
||||
.MaximumLength(2000);
|
||||
});
|
||||
|
||||
// PROFILE validation
|
||||
When(x => x.Entity == "PROFILE", () =>
|
||||
{
|
||||
RuleFor(x => x.Profile.Name)
|
||||
.NotEmpty()
|
||||
.WithMessage("PROFILE requires ProfileName (maps to @pPROFILE_NAME).")
|
||||
.MaximumLength(50);
|
||||
|
||||
RuleFor(x => x.Profile.Mandantor)
|
||||
.MaximumLength(50)
|
||||
.When(x => x.Profile.Mandantor != null);
|
||||
|
||||
RuleFor(x => x.Profile.Description)
|
||||
.MaximumLength(250)
|
||||
.When(x => x.Profile.Description != null);
|
||||
});
|
||||
|
||||
// RESULT validation
|
||||
When(x => x.Entity == "RESULT", () =>
|
||||
{
|
||||
RuleFor(x => x.Result.ActionId)
|
||||
.NotNull()
|
||||
.WithMessage("RESULT requires ResultActionId (maps to @pRESULT_ACTION_ID).");
|
||||
|
||||
RuleFor(x => x.Result.StatusId)
|
||||
.NotNull()
|
||||
.WithMessage("RESULT requires ResultStatusId (maps to @pRESULT_STATUS_ID).");
|
||||
});
|
||||
|
||||
// ENDPOINT_PARAMS validation
|
||||
When(x => x.Entity == "ENDPOINT_PARAMS", () =>
|
||||
{
|
||||
RuleFor(x => x.EndpointParams.GroupId)
|
||||
.NotNull()
|
||||
.WithMessage("ENDPOINT_PARAMS requires EndpointParamsGroupId (maps to @pENDPOINT_PARAMS_GROUP_ID).");
|
||||
});
|
||||
|
||||
// Simple length guards for some string fields (optional but cheap)
|
||||
RuleFor(x => x.AddedWho)
|
||||
.MaximumLength(50)
|
||||
.When(x => x.AddedWho != null);
|
||||
|
||||
RuleFor(x => x.Endpoint.Description)
|
||||
.MaximumLength(250)
|
||||
.When(x => x.Endpoint.Description != null);
|
||||
|
||||
RuleFor(x => x.EndpointAuth.Description)
|
||||
.MaximumLength(250)
|
||||
.When(x => x.EndpointAuth.Description != null);
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using ReC.Application.Common.Behaviors;
|
||||
using ReC.Application.Common.Constants;
|
||||
using ReC.Application.Common.Options;
|
||||
using ReC.Application.Common.Procedures;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ReC.Application;
|
||||
@@ -116,5 +118,23 @@ public static class DependencyInjection
|
||||
return this;
|
||||
}
|
||||
#endregion ConfigureRecActions
|
||||
|
||||
#region ConfigureSqlException
|
||||
public ConfigurationOptions ConfigureSqlException(Action<SqlExceptionOptions> configure)
|
||||
{
|
||||
_configActions.Enqueue(services => services.Configure(configure));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigurationOptions ConfigureSqlException(IConfiguration configuration)
|
||||
{
|
||||
_configActions.Enqueue(services =>
|
||||
{
|
||||
services.Configure<SqlExceptionOptions>(configuration);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
#endregion ConfigureSqlException
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
|
||||
namespace ReC.Application.EndpointAuth.Commands;
|
||||
|
||||
public record DeleteEndpointAuthProcedure : IDeleteProcedure
|
||||
{
|
||||
/// <summary>
|
||||
/// Start GUID/ID (inclusive)
|
||||
/// </summary>
|
||||
public long Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// End GUID/ID (inclusive). If 0, will be set to Start value.
|
||||
/// </summary>
|
||||
public long End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, delete even if dependent ACTION data exists
|
||||
/// </summary>
|
||||
public bool Force { get; set; }
|
||||
|
||||
public DeleteObjectProcedure ToObjectProcedure()
|
||||
{
|
||||
return new DeleteObjectProcedure
|
||||
{
|
||||
Entity = "ENDPOINT_AUTH",
|
||||
Start = Start,
|
||||
End = End,
|
||||
Force = Force
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
|
||||
namespace ReC.Application.EndpointAuth.Commands;
|
||||
|
||||
public record InsertEndpointAuthProcedure : IInsertProcedure
|
||||
{
|
||||
public bool? Active { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public byte? TypeId { get; set; }
|
||||
public string? ApiKey { get; set; }
|
||||
public string? ApiValue { get; set; }
|
||||
public bool? ApiKeyAddToId { get; set; }
|
||||
public string? Token { get; set; }
|
||||
public string? Username { get; set; }
|
||||
public string? Password { get; set; }
|
||||
public string? Domain { get; set; }
|
||||
public string? Workstation { get; set; }
|
||||
|
||||
public InsertObjectProcedure ToObjectProcedure(string? addedWho = null)
|
||||
{
|
||||
return new InsertObjectProcedure
|
||||
{
|
||||
Entity = "ENDPOINT_AUTH",
|
||||
EndpointAuth = this
|
||||
}.AddedBy(addedWho);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
|
||||
namespace ReC.Application.EndpointAuth.Commands;
|
||||
|
||||
public record UpdateEndpointAuthProcedure : IUpdateProcedure
|
||||
{
|
||||
public bool? Active { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public byte? TypeId { get; set; }
|
||||
public string? ApiKey { get; set; }
|
||||
public string? ApiValue { get; set; }
|
||||
public bool? ApiKeyAddToId { get; set; }
|
||||
public string? Token { get; set; }
|
||||
public string? Username { get; set; }
|
||||
public string? Password { get; set; }
|
||||
public string? Domain { get; set; }
|
||||
public string? Workstation { get; set; }
|
||||
|
||||
public UpdateObjectProcedure ToObjectProcedure(long id, string? changedWho = null)
|
||||
{
|
||||
return new UpdateObjectProcedure
|
||||
{
|
||||
Entity = "ENDPOINT_AUTH",
|
||||
Id = id,
|
||||
EndpointAuth = this
|
||||
}.ChangedBy(changedWho);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
|
||||
namespace ReC.Application.EndpointParams.Commands;
|
||||
|
||||
public record DeleteEndpointParamsProcedure : IDeleteProcedure
|
||||
{
|
||||
/// <summary>
|
||||
/// Start GUID/ID (inclusive)
|
||||
/// </summary>
|
||||
public long Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// End GUID/ID (inclusive). If 0, will be set to Start value.
|
||||
/// </summary>
|
||||
public long End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, delete even if dependent ACTION data exists
|
||||
/// </summary>
|
||||
public bool Force { get; set; }
|
||||
|
||||
public DeleteObjectProcedure ToObjectProcedure()
|
||||
{
|
||||
return new DeleteObjectProcedure
|
||||
{
|
||||
Entity = "ENDPOINT_PARAMS",
|
||||
Start = Start,
|
||||
End = End,
|
||||
Force = Force
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
|
||||
namespace ReC.Application.EndpointParams.Commands;
|
||||
|
||||
public record InsertEndpointParamsProcedure : IInsertProcedure
|
||||
{
|
||||
public bool? Active { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public short? GroupId { get; set; }
|
||||
public byte? Sequence { get; set; }
|
||||
public string? Key { get; set; }
|
||||
public string? Value { get; set; }
|
||||
|
||||
public InsertObjectProcedure ToObjectProcedure(string? addedWho = null)
|
||||
{
|
||||
return new InsertObjectProcedure
|
||||
{
|
||||
Entity = "ENDPOINT_PARAMS",
|
||||
EndpointParams = this
|
||||
}.AddedBy(addedWho);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
|
||||
namespace ReC.Application.EndpointParams.Commands;
|
||||
|
||||
public record UpdateEndpointParamsProcedure : IUpdateProcedure
|
||||
{
|
||||
public bool? Active { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public short? GroupId { get; set; }
|
||||
public byte? Sequence { get; set; }
|
||||
public string? Key { get; set; }
|
||||
public string? Value { get; set; }
|
||||
|
||||
public UpdateObjectProcedure ToObjectProcedure(long id, string? changedWho = null)
|
||||
{
|
||||
return new UpdateObjectProcedure
|
||||
{
|
||||
Entity = "ENDPOINT_PARAMS",
|
||||
Id = id,
|
||||
EndpointParams = this
|
||||
}.ChangedBy(changedWho);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
|
||||
namespace ReC.Application.Endpoints.Commands;
|
||||
|
||||
public record DeleteEndpointProcedure : IDeleteProcedure
|
||||
{
|
||||
/// <summary>
|
||||
/// Start GUID/ID (inclusive)
|
||||
/// </summary>
|
||||
public long Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// End GUID/ID (inclusive). If 0, will be set to Start value.
|
||||
/// </summary>
|
||||
public long End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, delete even if dependent ACTION data exists
|
||||
/// </summary>
|
||||
public bool Force { get; set; }
|
||||
|
||||
public DeleteObjectProcedure ToObjectProcedure()
|
||||
{
|
||||
return new DeleteObjectProcedure
|
||||
{
|
||||
Entity = "ENDPOINT",
|
||||
Start = Start,
|
||||
End = End,
|
||||
Force = Force
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
|
||||
namespace ReC.Application.Endpoints.Commands;
|
||||
|
||||
public record InsertEndpointProcedure : IInsertProcedure
|
||||
{
|
||||
public bool? Active { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Uri { get; set; }
|
||||
|
||||
public InsertObjectProcedure ToObjectProcedure(string? addedWho = null)
|
||||
{
|
||||
return new InsertObjectProcedure
|
||||
{
|
||||
Entity = "ENDPOINT",
|
||||
Endpoint = this
|
||||
}.AddedBy(addedWho);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ReC.Application.Common.Dto;
|
||||
using ReC.Domain.Entities;
|
||||
|
||||
namespace ReC.Application.Endpoints.Commands;
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class ObtainEndpointCommand : IRequest<EndpointDto>
|
||||
{
|
||||
public string Uri { get; init; } = null!;
|
||||
}
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class ObtainEndpointCommandHandler(IRepository<Endpoint> repo, IMapper mapper) : IRequestHandler<ObtainEndpointCommand, EndpointDto>
|
||||
{
|
||||
public async Task<EndpointDto> Handle(ObtainEndpointCommand request, CancellationToken cancel)
|
||||
{
|
||||
var endpoint = await repo.Where(e => e.Uri == request.Uri).FirstOrDefaultAsync(cancel);
|
||||
|
||||
if (endpoint is not null)
|
||||
return mapper.Map<EndpointDto>(endpoint);
|
||||
|
||||
endpoint = await repo.CreateAsync(request, cancel);
|
||||
return mapper.Map<EndpointDto>(endpoint);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
|
||||
namespace ReC.Application.Endpoints.Commands;
|
||||
|
||||
public record UpdateEndpointProcedure : IUpdateProcedure
|
||||
{
|
||||
public bool? Active { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Uri { get; set; }
|
||||
|
||||
public UpdateObjectProcedure ToObjectProcedure(long id, string? changedWho = null)
|
||||
{
|
||||
return new UpdateObjectProcedure
|
||||
{
|
||||
Entity = "ENDPOINT",
|
||||
Id = id,
|
||||
Endpoint = this
|
||||
}.ChangedBy(changedWho);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using ReC.Application.Endpoints.Commands;
|
||||
using ReC.Application.Common.Dto;
|
||||
|
||||
namespace ReC.Application.Endpoints;
|
||||
|
||||
// TODO: update to inject AddedWho from the current host/user contex
|
||||
public class MappingProfile : AutoMapper.Profile
|
||||
{
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public MappingProfile()
|
||||
{
|
||||
CreateMap<ObtainEndpointCommand, EndpointDto>()
|
||||
.ForMember(e => e.Active, exp => exp.MapFrom(cmd => true))
|
||||
.ForMember(e => e.AddedWhen, exp => exp.MapFrom(cmd => DateTime.UtcNow))
|
||||
.ForMember(e => e.AddedWho, exp => exp.MapFrom(cmd => "ReC.API"));
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using MediatR;
|
||||
using ReC.Domain.Entities;
|
||||
|
||||
namespace ReC.Application.OutResults.Commands;
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class CreateOutResCommand : IRequest
|
||||
{
|
||||
public required long ActionId { get; set; }
|
||||
|
||||
public short? Status { get; set; }
|
||||
|
||||
public string? Message { get; set; }
|
||||
|
||||
public string? Header { get; set; }
|
||||
|
||||
public string? Body { get; set; }
|
||||
|
||||
public string? AddedWho { get; set; }
|
||||
}
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class CreateOutResCommandHandler(IRepository<OutRes> repo) : IRequestHandler<CreateOutResCommand>
|
||||
{
|
||||
public Task Handle(CreateOutResCommand request, CancellationToken cancel)
|
||||
{
|
||||
return repo.CreateAsync(request, cancel);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using MediatR;
|
||||
using ReC.Application.Common.Interfaces;
|
||||
using ReC.Domain.Views;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ReC.Application.OutResults.Commands;
|
||||
|
||||
public class CreateResultViewCommand : IAuthScoped, IRequest
|
||||
{
|
||||
public required long ActionId { get; set; }
|
||||
|
||||
public required short StatusCode { get; set; }
|
||||
|
||||
public string? Header { get; set; }
|
||||
|
||||
public string? Body { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public AuthScope Scope { get; } = new();
|
||||
}
|
||||
|
||||
public class CreateResultViewCommandHandler(IRepository<ResultView> repo) : IRequestHandler<CreateResultViewCommand>
|
||||
{
|
||||
public Task Handle(CreateResultViewCommand request, CancellationToken cancel) => repo.CreateAsync(request, cancel);
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using MediatR;
|
||||
using ReC.Domain.Entities;
|
||||
|
||||
namespace ReC.Application.OutResults.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the command to delete output results based on specified criteria.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Deletion can be performed by providing either an <see cref="ActionId"/> or a <see cref="ProfileId"/>.
|
||||
/// At least one of these properties must be set for the operation to proceed.
|
||||
/// </remarks>
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public record DeleteOutResCommand : IRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the unique identifier for the action whose output results should be deleted.
|
||||
/// </summary>
|
||||
public long? ActionId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique identifier for the profile whose associated action's output results should be deleted.
|
||||
/// </summary>
|
||||
public long? ProfileId { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the execution of the <see cref="DeleteOutResCommand"/>.
|
||||
/// </summary>
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class DeleteOutResCommandHandler(IRepository<OutRes> repo) : IRequestHandler<DeleteOutResCommand>
|
||||
{
|
||||
/// <summary>
|
||||
/// Processes the delete command by removing matching <see cref="OutRes"/> entities from the repository.
|
||||
/// </summary>
|
||||
/// <param name="request">The command containing the deletion criteria.</param>
|
||||
/// <param name="cancel">A cancellation token that can be used to cancel the work.</param>
|
||||
/// <returns>A task that represents the asynchronous delete operation.</returns>
|
||||
/// <remarks>
|
||||
/// The handler deletes records where <c>OutRes.ActionId</c> matches <see cref="DeleteOutResCommand.ActionId"/>
|
||||
/// or where the associated <c>Action.ProfileId</c> matches <see cref="DeleteOutResCommand.ProfileId"/>.
|
||||
/// </remarks>
|
||||
public Task Handle(DeleteOutResCommand request, CancellationToken cancel)
|
||||
{
|
||||
return repo.DeleteAsync(x => x.ActionId == request.ActionId || x.Action!.ProfileId == request.ProfileId, cancel);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace ReC.Application.OutResults.Commands;
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class DeleteOutResCommandValidator : AbstractValidator<DeleteOutResCommand>
|
||||
{
|
||||
public DeleteOutResCommandValidator()
|
||||
{
|
||||
RuleFor(x => x)
|
||||
.Must(x => x.ActionId.HasValue || x.ProfileId.HasValue)
|
||||
.WithMessage("At least one of ActionId or ProfileId must be provided.")
|
||||
.WithName("Identifier");
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using ReC.Application.OutResults.Commands;
|
||||
using ReC.Domain.Entities;
|
||||
using ReC.Domain.Views;
|
||||
|
||||
namespace ReC.Application.OutResults;
|
||||
|
||||
// TODO: update to inject AddedWho from the current host/user contex
|
||||
public class MappingProfiles : AutoMapper.Profile
|
||||
{
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public MappingProfiles()
|
||||
{
|
||||
CreateMap<CreateOutResCommand, OutRes>()
|
||||
.ForMember(e => e.AddedWhen, exp => exp.MapFrom(cmd => DateTime.UtcNow))
|
||||
.ForMember(e => e.AddedWho, exp => exp.MapFrom(cmd => "ReC.API"));
|
||||
|
||||
CreateMap<CreateResultViewCommand, ResultView>()
|
||||
.ForMember(e => e.AddedWhen, exp => exp.MapFrom(cmd => DateTime.UtcNow));
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ReC.Application.Common.Dto;
|
||||
using ReC.Domain.Entities;
|
||||
|
||||
namespace ReC.Application.OutResults.Queries;
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public record ReadOutResQuery : IRequest<IEnumerable<OutResDto>>
|
||||
{
|
||||
public long? ProfileId { get; init; }
|
||||
|
||||
public long? ActionId { get; init; }
|
||||
}
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class ReadOutResHandler(IRepository<OutRes> repo, IMapper mapper) : IRequestHandler<ReadOutResQuery, IEnumerable<OutResDto>>
|
||||
{
|
||||
public async Task<IEnumerable<OutResDto>> Handle(ReadOutResQuery request, CancellationToken cancel)
|
||||
{
|
||||
var q = repo.Query;
|
||||
|
||||
if(request.ActionId is long actionId)
|
||||
q = q.Where(res => res.ActionId == actionId);
|
||||
|
||||
if(request.ProfileId is long profileId)
|
||||
q = q.Where(res => res.Action!.ProfileId == profileId);
|
||||
|
||||
var resList = await q.ToListAsync(cancel);
|
||||
|
||||
if (resList.Count == 0)
|
||||
throw new NotFoundException();
|
||||
|
||||
return mapper.Map<IEnumerable<OutResDto>>(resList);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace ReC.Application.OutResults.Queries;
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class ReadOutResQueryValidator : AbstractValidator<ReadOutResQuery>
|
||||
{
|
||||
public ReadOutResQueryValidator()
|
||||
{
|
||||
RuleFor(x => x)
|
||||
.Must(x => x.ActionId.HasValue || x.ProfileId.HasValue)
|
||||
.WithMessage("At least one of ActionId or ProfileId must be provided.")
|
||||
.WithName("Identifier");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
|
||||
namespace ReC.Application.Profile.Commands;
|
||||
|
||||
public record DeleteProfileProcedure : IDeleteProcedure
|
||||
{
|
||||
/// <summary>
|
||||
/// Start GUID/ID (inclusive)
|
||||
/// </summary>
|
||||
public long Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// End GUID/ID (inclusive). If 0, will be set to Start value.
|
||||
/// </summary>
|
||||
public long End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, delete even if dependent ACTION data exists
|
||||
/// </summary>
|
||||
public bool Force { get; set; }
|
||||
|
||||
public DeleteObjectProcedure ToObjectProcedure()
|
||||
{
|
||||
return new DeleteObjectProcedure
|
||||
{
|
||||
Entity = "PROFILE",
|
||||
Start = Start,
|
||||
End = End,
|
||||
Force = Force
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
|
||||
namespace ReC.Application.Profile.Commands;
|
||||
|
||||
public record InsertProfileProcedure : IInsertProcedure
|
||||
{
|
||||
public bool? Active { get; set; }
|
||||
public byte? TypeId { get; set; }
|
||||
public string? Mandantor { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public byte? LogLevelId { get; set; }
|
||||
public short? LanguageId { get; set; }
|
||||
|
||||
public InsertObjectProcedure ToObjectProcedure(string? addedWho = null)
|
||||
{
|
||||
return new InsertObjectProcedure
|
||||
{
|
||||
Entity = "PROFILE",
|
||||
Profile = this
|
||||
}.AddedBy(addedWho);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
|
||||
namespace ReC.Application.Profile.Commands;
|
||||
|
||||
public record UpdateProfileProcedure : IUpdateProcedure
|
||||
{
|
||||
public bool? Active { get; set; }
|
||||
public byte? TypeId { get; set; }
|
||||
public string? Mandantor { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public byte? LogLevelId { get; set; }
|
||||
public short? LanguageId { get; set; }
|
||||
public DateTime? FirstRun { get; set; }
|
||||
public DateTime? LastRun { get; set; }
|
||||
public string? LastResult { get; set; }
|
||||
|
||||
public UpdateObjectProcedure ToObjectProcedure(long id, string? changedWho = null)
|
||||
{
|
||||
return new UpdateObjectProcedure
|
||||
{
|
||||
Entity = "PROFILE",
|
||||
Id = id,
|
||||
Profile = this
|
||||
}.ChangedBy(changedWho);
|
||||
}
|
||||
}
|
||||
36
src/ReC.Application/Profile/Queries/ReadProfileViewQuery.cs
Normal file
36
src/ReC.Application/Profile/Queries/ReadProfileViewQuery.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ReC.Application.Common.Dto;
|
||||
using ReC.Domain.Views;
|
||||
|
||||
namespace ReC.Application.Profile.Queries;
|
||||
|
||||
public record ReadProfileViewQuery : IRequest<IEnumerable<ProfileViewDto>>
|
||||
{
|
||||
public long? Id { get; init; } = null;
|
||||
|
||||
public bool IncludeActions { get; init; } = true;
|
||||
}
|
||||
|
||||
public class ReadProfileViewQueryHandler(IRepository<ProfileView> repo, IMapper mapper)
|
||||
: IRequestHandler<ReadProfileViewQuery, IEnumerable<ProfileViewDto>>
|
||||
{
|
||||
public async Task<IEnumerable<ProfileViewDto>> Handle(ReadProfileViewQuery request, CancellationToken cancel)
|
||||
{
|
||||
var query = request.IncludeActions
|
||||
? repo.Query.Include(p => p.Actions)
|
||||
: repo.Query;
|
||||
|
||||
if (request.Id is long id)
|
||||
query = query.Where(p => p.Id == id);
|
||||
|
||||
var profiles = await query.ToListAsync(cancel);
|
||||
|
||||
return profiles is null || profiles.Count == 0
|
||||
? throw new NotFoundException($"Profile {request.Id} not found.")
|
||||
: mapper.Map<IEnumerable<ProfileViewDto>>(profiles);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
<PackageReference Include="AutoMapper" Version="15.1.0" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.6.0" />
|
||||
<PackageReference Include="DigitalData.Core.Application" Version="3.4.0" />
|
||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.1" />
|
||||
<PackageReference Include="FluentValidation" Version="12.1.0" />
|
||||
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="12.1.0" />
|
||||
<PackageReference Include="MediatR" Version="13.1.0" />
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using MediatR;
|
||||
using ReC.Domain.Entities;
|
||||
using ReC.Application.Endpoints.Commands;
|
||||
|
||||
namespace ReC.Application.RecActions.Commands;
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public record CreateRecActionCommand : IRequest
|
||||
{
|
||||
public long ProfileId { get; init; }
|
||||
|
||||
public bool Active { get; init; } = true;
|
||||
|
||||
public long? EndpointId { get; set; }
|
||||
|
||||
public string? EndpointUri { get; init; }
|
||||
|
||||
public string Type { get; init; } = null!;
|
||||
|
||||
public string? HeaderQuery { get; init; }
|
||||
|
||||
public string BodyQuery { get; init; } = null!;
|
||||
|
||||
public byte Sequence { get; set; } = 1;
|
||||
|
||||
public long? EndpointAuthId { get; set; }
|
||||
}
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class CreateRecActionCommandHandler(ISender sender, IRepository<RecAction> repo) : IRequestHandler<CreateRecActionCommand>
|
||||
{
|
||||
public async Task Handle(CreateRecActionCommand request, CancellationToken cancel)
|
||||
{
|
||||
if(request.EndpointId is null)
|
||||
if(request.EndpointUri is string endpointUri)
|
||||
{
|
||||
var endpoint = await sender.Send(new ObtainEndpointCommand { Uri = endpointUri }, cancel);
|
||||
request.EndpointId = endpoint.Id;
|
||||
}
|
||||
else
|
||||
throw new BadRequestException("Either EndpointId or EndpointUri must be provided.");
|
||||
|
||||
await repo.CreateAsync(request, cancel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
|
||||
namespace ReC.Application.RecActions.Commands;
|
||||
|
||||
public record DeleteActionProcedure : IDeleteProcedure
|
||||
{
|
||||
/// <summary>
|
||||
/// Start GUID/ID (inclusive)
|
||||
/// </summary>
|
||||
public long Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// End GUID/ID (inclusive). If 0, will be set to Start value.
|
||||
/// </summary>
|
||||
public long End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, delete even if dependent RESULT data exists
|
||||
/// </summary>
|
||||
public bool Force { get; set; }
|
||||
|
||||
public DeleteObjectProcedure ToObjectProcedure()
|
||||
{
|
||||
return new DeleteObjectProcedure
|
||||
{
|
||||
Entity = "ACTION",
|
||||
Start = Start,
|
||||
End = End,
|
||||
Force = Force
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ReC.Domain.Entities;
|
||||
|
||||
namespace ReC.Application.RecActions.Commands;
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class DeleteRecActionsCommand : IRequest
|
||||
{
|
||||
public required long ProfileId { get; init; }
|
||||
}
|
||||
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public class DeleteRecActionsCommandHandler(IRepository<RecAction> repo) : IRequestHandler<DeleteRecActionsCommand>
|
||||
{
|
||||
public async Task Handle(DeleteRecActionsCommand request, CancellationToken cancel)
|
||||
{
|
||||
// TODO: update DeleteAsync (in Core) to return number of deleted records
|
||||
if (!await repo.Where(act => act.ProfileId == request.ProfileId).AnyAsync(cancel))
|
||||
throw new NotFoundException();
|
||||
|
||||
await repo.DeleteAsync(act => act.ProfileId == request.ProfileId, cancel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Domain.Constants;
|
||||
|
||||
namespace ReC.Application.RecActions.Commands;
|
||||
|
||||
public record InsertActionProcedure : IInsertProcedure
|
||||
{
|
||||
public long? ProfileId { get; set; }
|
||||
public bool? Active { get; set; }
|
||||
public byte? Sequence { get; set; }
|
||||
public long? EndpointId { get; set; }
|
||||
public long? EndpointAuthId { get; set; }
|
||||
public short? EndpointParamsId { get; set; }
|
||||
public short? SqlConnectionId { get; set; }
|
||||
public RestType? TypeId { get; set; }
|
||||
public string? PreSql { get; set; }
|
||||
public string? HeaderSql { get; set; }
|
||||
public string? BodySql { get; set; }
|
||||
public string? PostSql { get; set; }
|
||||
public byte? ErrorActionId { get; set; }
|
||||
|
||||
public InsertObjectProcedure ToObjectProcedure(string? addedWho = null)
|
||||
{
|
||||
return new InsertObjectProcedure
|
||||
{
|
||||
Entity = "ACTION",
|
||||
Action = this
|
||||
}.AddedBy(addedWho);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,8 @@ using ReC.Application.Common;
|
||||
using ReC.Application.Common.Constants;
|
||||
using ReC.Application.Common.Dto;
|
||||
using ReC.Application.Common.Exceptions;
|
||||
using ReC.Application.OutResults.Commands;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Results.Commands;
|
||||
using ReC.Domain.Constants;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
@@ -133,14 +134,13 @@ public class InvokeRecActionViewCommandHandler(
|
||||
|
||||
var statusCode = (short)response.StatusCode;
|
||||
|
||||
await sender.Send(new CreateOutResCommand
|
||||
await sender.ExecuteInsertProcedure(new InsertResultProcedure()
|
||||
{
|
||||
Status = statusCode,
|
||||
StatusId = statusCode,
|
||||
ActionId = action.Id,
|
||||
Header = JsonSerializer.Serialize(resHeaders, options: new() { WriteIndented = false }),
|
||||
Body = resBody,
|
||||
AddedWho = config?["AddedWho"]
|
||||
}, cancel);
|
||||
Body = resBody
|
||||
}, config?["AddedWho"], cancel);
|
||||
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
|
||||
namespace ReC.Application.RecActions.Commands;
|
||||
|
||||
public record UpdateActionProcedure : IUpdateProcedure
|
||||
{
|
||||
public long? ProfileId { get; set; }
|
||||
public bool? Active { get; set; }
|
||||
public byte? Sequence { get; set; }
|
||||
public long? EndpointId { get; set; }
|
||||
public long? EndpointAuthId { get; set; }
|
||||
public short? EndpointParamsId { get; set; }
|
||||
public short? SqlConnectionId { get; set; }
|
||||
public byte? TypeId { get; set; }
|
||||
public string? PreSql { get; set; }
|
||||
public string? HeaderSql { get; set; }
|
||||
public string? BodySql { get; set; }
|
||||
public string? PostSql { get; set; }
|
||||
public byte? ErrorActionId { get; set; }
|
||||
|
||||
public UpdateObjectProcedure ToObjectProcedure(long id, string? changedWho = null)
|
||||
{
|
||||
return new UpdateObjectProcedure
|
||||
{
|
||||
Entity = "ACTION",
|
||||
Id = id,
|
||||
Action = this
|
||||
}.ChangedBy(changedWho);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using ReC.Application.Common.Dto;
|
||||
using ReC.Application.RecActions.Commands;
|
||||
|
||||
namespace ReC.Application.RecActions;
|
||||
|
||||
// TODO: update to inject AddedWho from the current host/user contex
|
||||
public class MappingProfile : AutoMapper.Profile
|
||||
{
|
||||
[Obsolete("Use the related procedure or view.")]
|
||||
public MappingProfile()
|
||||
{
|
||||
CreateMap<CreateRecActionCommand, RecActionDto>()
|
||||
.ForMember(e => e.Active, exp => exp.MapFrom(cmd => true))
|
||||
.ForMember(e => e.AddedWhen, exp => exp.MapFrom(cmd => DateTime.UtcNow))
|
||||
.ForMember(e => e.AddedWho, exp => exp.MapFrom(cmd => "ReC.API"));
|
||||
}
|
||||
}
|
||||
@@ -25,9 +25,11 @@ public class ReadRecActionViewQueryHandler(IRepository<RecActionView> repo, IMap
|
||||
query = repo.Where(act => act.ProfileId == profileId);
|
||||
|
||||
if (request.Invoked is bool invoked)
|
||||
query = invoked ? query.Where(act => act.Root!.OutRes != null) : query.Where(act => act.Root!.OutRes == null);
|
||||
query = invoked
|
||||
? query.Where(act => act.Results!.Any())
|
||||
: query.Where(act => !act.Results!.Any());
|
||||
|
||||
var actions = await query.Include(act => act.EndpointAuth).ToListAsync(cancel);
|
||||
var actions = await query.ToListAsync(cancel);
|
||||
|
||||
if (actions.Count == 0)
|
||||
throw new NotFoundException($"No actions found for the profile {request.ProfileId}.");
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
|
||||
namespace ReC.Application.Results.Commands;
|
||||
|
||||
public record DeleteResultProcedure : IDeleteProcedure
|
||||
{
|
||||
/// <summary>
|
||||
/// Start GUID/ID (inclusive)
|
||||
/// </summary>
|
||||
public long Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// End GUID/ID (inclusive). If 0, will be set to Start value.
|
||||
/// </summary>
|
||||
public long End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Force parameter (not used for RESULT entity as it has no dependencies)
|
||||
/// </summary>
|
||||
public bool Force { get; set; }
|
||||
|
||||
public DeleteObjectProcedure ToObjectProcedure()
|
||||
{
|
||||
return new DeleteObjectProcedure
|
||||
{
|
||||
Entity = "RESULT",
|
||||
Start = Start,
|
||||
End = End,
|
||||
Force = Force
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
|
||||
namespace ReC.Application.Results.Commands;
|
||||
|
||||
public record InsertResultProcedure : IInsertProcedure
|
||||
{
|
||||
public long? ActionId { get; set; }
|
||||
public short? StatusId { get; set; }
|
||||
public string? Header { get; set; }
|
||||
public string? Body { get; set; }
|
||||
|
||||
public InsertObjectProcedure ToObjectProcedure(string? addedWho = null)
|
||||
{
|
||||
return new InsertObjectProcedure
|
||||
{
|
||||
Entity = "RESULT",
|
||||
Result = this
|
||||
}.AddedBy(addedWho ?? "Rec.API");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
|
||||
namespace ReC.Application.Results.Commands;
|
||||
|
||||
public record UpdateResultProcedure : IUpdateProcedure
|
||||
{
|
||||
public long? ActionId { get; set; }
|
||||
public short? StatusId { get; set; }
|
||||
public string? Header { get; set; }
|
||||
public string? Body { get; set; }
|
||||
|
||||
public UpdateObjectProcedure ToObjectProcedure(long id, string? changedWho = null)
|
||||
{
|
||||
return new UpdateObjectProcedure
|
||||
{
|
||||
Entity = "RESULT",
|
||||
Id = id,
|
||||
Result = this
|
||||
}.ChangedBy(changedWho);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using ReC.Application.Common.Dto;
|
||||
using ReC.Domain.Views;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ReC.Application.OutResults.Queries;
|
||||
namespace ReC.Application.Results.Queries;
|
||||
|
||||
public record ReadResultViewQuery : IRequest<IEnumerable<ResultViewDto>>
|
||||
{
|
||||
71
src/ReC.Client/Api/BaseCrudApi.cs
Normal file
71
src/ReC.Client/Api/BaseCrudApi.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ReC.Client.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides shared CRUD operations for API resources.
|
||||
/// </summary>
|
||||
public abstract class BaseCrudApi
|
||||
{
|
||||
/// <summary>
|
||||
/// The HTTP client used to send requests.
|
||||
/// </summary>
|
||||
protected readonly HttpClient Http;
|
||||
|
||||
/// <summary>
|
||||
/// The base resource path for the API endpoint.
|
||||
/// </summary>
|
||||
protected readonly string ResourcePath;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseCrudApi"/> class.
|
||||
/// </summary>
|
||||
/// <param name="http">The HTTP client used for requests.</param>
|
||||
/// <param name="resourcePath">The base resource path for the API endpoint.</param>
|
||||
protected BaseCrudApi(HttpClient http, string resourcePath)
|
||||
{
|
||||
Http = http ?? throw new ArgumentNullException(nameof(http));
|
||||
ResourcePath = resourcePath ?? throw new ArgumentNullException(nameof(resourcePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a resource.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The payload type.</typeparam>
|
||||
/// <param name="payload">The payload to send.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public Task<HttpResponseMessage> CreateAsync<T>(T payload, CancellationToken cancel = default)
|
||||
=> Http.PostAsync(ResourcePath, ReCClientHelpers.ToJsonContent(payload), cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a resource by identifier.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The payload type.</typeparam>
|
||||
/// <param name="id">The resource identifier.</param>
|
||||
/// <param name="payload">The payload to send.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public Task<HttpResponseMessage> UpdateAsync<T>(long id, T payload, CancellationToken cancel = default)
|
||||
=> Http.PutAsync($"{ResourcePath}/{id}", ReCClientHelpers.ToJsonContent(payload), cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes resources with identifiers supplied in the payload.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The payload type containing identifiers.</typeparam>
|
||||
/// <param name="payload">The payload to send.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public Task<HttpResponseMessage> DeleteAsync<T>(T payload, CancellationToken cancel = default)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Delete, ResourcePath)
|
||||
{
|
||||
Content = ReCClientHelpers.ToJsonContent(payload)
|
||||
};
|
||||
return Http.SendAsync(request, cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/ReC.Client/Api/CommonApi.cs
Normal file
20
src/ReC.Client/Api/CommonApi.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ReC.Client.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to common object endpoints.
|
||||
/// </summary>
|
||||
public class CommonApi : BaseCrudApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CommonApi"/> class.
|
||||
/// </summary>
|
||||
/// <param name="http">The HTTP client used for requests.</param>
|
||||
public CommonApi(HttpClient http) : base(http, "api/Common")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/ReC.Client/Api/EndpointAuthApi.cs
Normal file
20
src/ReC.Client/Api/EndpointAuthApi.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ReC.Client.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to endpoint authentication endpoints.
|
||||
/// </summary>
|
||||
public class EndpointAuthApi : BaseCrudApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EndpointAuthApi"/> class.
|
||||
/// </summary>
|
||||
/// <param name="http">The HTTP client used for requests.</param>
|
||||
public EndpointAuthApi(HttpClient http) : base(http, "api/EndpointAuth")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/ReC.Client/Api/EndpointParamsApi.cs
Normal file
20
src/ReC.Client/Api/EndpointParamsApi.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ReC.Client.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to endpoint parameter endpoints.
|
||||
/// </summary>
|
||||
public class EndpointParamsApi : BaseCrudApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EndpointParamsApi"/> class.
|
||||
/// </summary>
|
||||
/// <param name="http">The HTTP client used for requests.</param>
|
||||
public EndpointParamsApi(HttpClient http) : base(http, "api/EndpointParams")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/ReC.Client/Api/EndpointsApi.cs
Normal file
20
src/ReC.Client/Api/EndpointsApi.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ReC.Client.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to endpoint definitions.
|
||||
/// </summary>
|
||||
public class EndpointsApi : BaseCrudApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EndpointsApi"/> class.
|
||||
/// </summary>
|
||||
/// <param name="http">The HTTP client used for requests.</param>
|
||||
public EndpointsApi(HttpClient http) : base(http, "api/Endpoints")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/ReC.Client/Api/ProfileApi.cs
Normal file
33
src/ReC.Client/Api/ProfileApi.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ReC.Client.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to profile endpoints.
|
||||
/// </summary>
|
||||
public class ProfileApi : BaseCrudApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ProfileApi"/> class.
|
||||
/// </summary>
|
||||
/// <param name="http">The HTTP client used for requests.</param>
|
||||
public ProfileApi(HttpClient http) : base(http, "api/Profile")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a profile by identifier.
|
||||
/// </summary>
|
||||
/// <param name="id">The profile identifier.</param>
|
||||
/// <param name="includeActions">Whether to include related actions.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public Task<HttpResponseMessage> GetAsync(long id, bool includeActions = false, CancellationToken cancel = default)
|
||||
{
|
||||
var query = ReCClientHelpers.BuildQuery(("Id", id), ("IncludeActions", includeActions));
|
||||
return Http.GetAsync($"{ResourcePath}{query}", cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/ReC.Client/Api/RecActionApi.cs
Normal file
45
src/ReC.Client/Api/RecActionApi.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ReC.Client.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to RecAction endpoints.
|
||||
/// </summary>
|
||||
public class RecActionApi : BaseCrudApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RecActionApi"/> class.
|
||||
/// </summary>
|
||||
/// <param name="http">The HTTP client used for requests.</param>
|
||||
public RecActionApi(HttpClient http) : base(http, "api/RecAction")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a ReC action for the specified profile.
|
||||
/// </summary>
|
||||
/// <param name="profileId">The profile identifier.</param>
|
||||
/// <param name="cancellationToken">A token to cancel the operation.</param>
|
||||
/// <returns><see langword="true"/> if the request succeeds; otherwise, <see langword="false"/>.</returns>
|
||||
public async Task<bool> InvokeAsync(int profileId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resp = await Http.PostAsync($"{ResourcePath}/invoke/{profileId}", content: null, cancellationToken);
|
||||
return resp.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves Rec actions.
|
||||
/// </summary>
|
||||
/// <param name="profileId">Optional profile filter.</param>
|
||||
/// <param name="invoked">Optional invoked filter.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public Task<HttpResponseMessage> GetAsync(long? profileId = null, bool? invoked = null, CancellationToken cancel = default)
|
||||
{
|
||||
var query = ReCClientHelpers.BuildQuery(("ProfileId", profileId), ("Invoked", invoked));
|
||||
return Http.GetAsync($"{ResourcePath}{query}", cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/ReC.Client/Api/ResultApi.cs
Normal file
34
src/ReC.Client/Api/ResultApi.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ReC.Client.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to output result endpoints.
|
||||
/// </summary>
|
||||
public class ResultApi : BaseCrudApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ResultApi"/> class.
|
||||
/// </summary>
|
||||
/// <param name="http">The HTTP client used for requests.</param>
|
||||
public ResultApi(HttpClient http) : base(http, "api/Result")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves results with optional filters.
|
||||
/// </summary>
|
||||
/// <param name="id">Optional result identifier.</param>
|
||||
/// <param name="actionId">Optional action identifier.</param>
|
||||
/// <param name="profileId">Optional profile identifier.</param>
|
||||
/// <param name="cancel">A token to cancel the operation.</param>
|
||||
/// <returns>The HTTP response message.</returns>
|
||||
public Task<HttpResponseMessage> GetAsync(long? id = null, long? actionId = null, long? profileId = null, CancellationToken cancel = default)
|
||||
{
|
||||
var query = ReCClientHelpers.BuildQuery(("Id", id), ("ActionId", actionId), ("ProfileId", profileId));
|
||||
return Http.GetAsync($"{ResourcePath}{query}", cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,8 +30,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
</ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using ReC.Client.Api;
|
||||
|
||||
namespace ReC.Client
|
||||
{
|
||||
@@ -21,6 +17,41 @@ namespace ReC.Client
|
||||
/// </summary>
|
||||
public static readonly string ClientName = Guid.NewGuid().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to RecAction endpoints.
|
||||
/// </summary>
|
||||
public RecActionApi RecActions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to Result endpoints.
|
||||
/// </summary>
|
||||
public ResultApi Results { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to Profile endpoints.
|
||||
/// </summary>
|
||||
public ProfileApi Profiles { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to EndpointAuth endpoints.
|
||||
/// </summary>
|
||||
public EndpointAuthApi EndpointAuth { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to EndpointParams endpoints.
|
||||
/// </summary>
|
||||
public EndpointParamsApi EndpointParams { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to Endpoints endpoints.
|
||||
/// </summary>
|
||||
public EndpointsApi Endpoints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to Common endpoints.
|
||||
/// </summary>
|
||||
public CommonApi Common { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ReCClient"/> class.
|
||||
/// </summary>
|
||||
@@ -28,37 +59,13 @@ namespace ReC.Client
|
||||
public ReCClient(IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
_http = httpClientFactory.CreateClient(ClientName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously invokes a ReC action for a specific profile.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method sends a POST request to the <c>api/RecAction/invoke/{profileId}</c> endpoint.
|
||||
/// </remarks>
|
||||
/// <param name="profileId">The ID of the profile to invoke the action for.</param>
|
||||
/// <param name="cancellationToken">A token to cancel the asynchronous operation.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous operation. The task result is <see langword="true"/> if the request was successful; otherwise, <see langword="false"/>.</returns>
|
||||
public async Task<bool> InvokeRecActionAsync(int profileId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var resp = await _http.PostAsync($"api/RecAction/invoke/{profileId}", content: null, cancellationToken);
|
||||
return resp.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synchronously invokes a ReC action for a specific profile.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method sends a POST request to the <c>api/RecAction/invoke/{profileId}</c> endpoint.
|
||||
/// This is the synchronous version of <see cref="InvokeRecActionAsync(int, CancellationToken)"/>.
|
||||
/// </remarks>
|
||||
/// <param name="profileId">The ID of the profile to invoke the action for.</param>
|
||||
/// <returns><see langword="true"/> if the request was successful; otherwise, <see langword="false"/>.</returns>
|
||||
[Obsolete("Use InvokeRecActionAsync instead to avoid potential deadlocks and improve performance.")]
|
||||
public bool InvokeRecAction(int profileId)
|
||||
{
|
||||
var resp = _http.PostAsync($"api/RecAction/invoke/{profileId}", content: null).GetAwaiter().GetResult();
|
||||
return resp.IsSuccessStatusCode;
|
||||
RecActions = new RecActionApi(_http);
|
||||
Results = new ResultApi(_http);
|
||||
Profiles = new ProfileApi(_http);
|
||||
EndpointAuth = new EndpointAuthApi(_http);
|
||||
EndpointParams = new EndpointParamsApi(_http);
|
||||
Endpoints = new EndpointsApi(_http);
|
||||
Common = new CommonApi(_http);
|
||||
}
|
||||
|
||||
#region Static
|
||||
@@ -121,4 +128,23 @@ namespace ReC.Client
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies which part of the result to return for result view endpoints.
|
||||
/// </summary>
|
||||
public enum ResultType
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns both header and body.
|
||||
/// </summary>
|
||||
Full,
|
||||
/// <summary>
|
||||
/// Returns only the header portion of the result.
|
||||
/// </summary>
|
||||
OnlyHeader,
|
||||
/// <summary>
|
||||
/// Returns only the body portion of the result.
|
||||
/// </summary>
|
||||
OnlyBody
|
||||
}
|
||||
}
|
||||
49
src/ReC.Client/ReCClientHelpers.cs
Normal file
49
src/ReC.Client/ReCClientHelpers.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using System.Net.Http;
|
||||
#endif
|
||||
|
||||
namespace ReC.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides shared helpers for composing requests.
|
||||
/// </summary>
|
||||
internal static class ReCClientHelpers
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
/// <summary>
|
||||
/// Builds a query string from the provided key/value pairs, skipping null values.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The key/value pairs to include in the query string.</param>
|
||||
/// <returns>A query string beginning with '?', or an empty string if no values are provided.</returns>
|
||||
public static string BuildQuery(params (string Key, object Value)[] parameters)
|
||||
#else
|
||||
/// <summary>
|
||||
/// Builds a query string from the provided key/value pairs, skipping null values.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The key/value pairs to include in the query string.</param>
|
||||
/// <returns>A query string beginning with '?', or an empty string if no values are provided.</returns>
|
||||
public static string BuildQuery(params (string Key, object? Value)[] parameters)
|
||||
#endif
|
||||
{
|
||||
var parts = parameters
|
||||
.Where(p => p.Value != null)
|
||||
.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(Convert.ToString(p.Value, CultureInfo.InvariantCulture) ?? string.Empty)}");
|
||||
|
||||
var query = string.Join("&", parts);
|
||||
return string.IsNullOrWhiteSpace(query) ? string.Empty : $"?{query}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a JSON content payload from the provided object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the payload.</typeparam>
|
||||
/// <param name="payload">The payload to serialize.</param>
|
||||
/// <returns>A <see cref="JsonContent"/> instance ready for HTTP requests.</returns>
|
||||
public static JsonContent ToJsonContent<T>(T payload) => JsonContent.Create(payload);
|
||||
}
|
||||
}
|
||||
26
src/ReC.Client/TaskSyncExtensions.cs
Normal file
26
src/ReC.Client/TaskSyncExtensions.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
#if NETFRAMEWORK
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
|
||||
namespace ReC.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides synchronous wrappers for Task-based operations.
|
||||
/// </summary>
|
||||
public static class TaskSyncExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Blocks until the task completes and propagates any exception.
|
||||
/// </summary>
|
||||
/// <param name="task">The task to wait for.</param>
|
||||
public static void Sync(this Task task) => task.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
/// <summary>
|
||||
/// Blocks until the task completes and returns its result, propagating any exception.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the task result.</typeparam>
|
||||
/// <param name="task">The task to wait for.</param>
|
||||
/// <returns>The result of the completed task.</returns>
|
||||
public static TResult Sync<TResult>(this Task<TResult> task) => task.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Domain.Entities;
|
||||
|
||||
[Table("TBDD_CONNECTION")]
|
||||
public class Connection
|
||||
{
|
||||
public short? Id { get; set; }
|
||||
|
||||
public string? Bezeichnung { get; set; }
|
||||
|
||||
public string? SqlProvider { get; set; }
|
||||
|
||||
public string? Server { get; set; }
|
||||
|
||||
public string? Datenbank { get; set; }
|
||||
|
||||
public string? Username { get; set; }
|
||||
|
||||
public string? Password { get; set; }
|
||||
|
||||
public string? Bemerkung { get; set; }
|
||||
|
||||
public bool? Aktiv { get; set; }
|
||||
|
||||
public string? ErstelltWer { get; set; }
|
||||
|
||||
public DateTime? ErstelltWann { get; set; }
|
||||
|
||||
public string? GeandertWer { get; set; }
|
||||
|
||||
public DateTime? GeaendertWann { get; set; }
|
||||
|
||||
public bool? SysConnection { get; set; }
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Domain.Entities;
|
||||
|
||||
[Table("TBREC_CFG_ENDPOINT")]
|
||||
public class Endpoint
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public bool? Active { get; set; }
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public string? Uri { get; set; }
|
||||
|
||||
public string? AddedWho { get; set; }
|
||||
|
||||
public DateTime? AddedWhen { get; set; }
|
||||
|
||||
public string? ChangedWho { get; set; }
|
||||
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using ReC.Domain.Constants;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Domain.Entities;
|
||||
|
||||
[Table("TBREC_CFG_ENDPOINT_AUTH")]
|
||||
public class EndpointAuth
|
||||
{
|
||||
public long? Id { get; set; }
|
||||
|
||||
public bool? Active { get; set; }
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public EndpointAuthType? Type { get; set; }
|
||||
|
||||
public string? ApiKey { get; set; }
|
||||
|
||||
public string? ApiValue { get; set; }
|
||||
|
||||
public ApiKeyLocation? ApiKeyAddTo { get; set; }
|
||||
|
||||
public string? Token { get; set; }
|
||||
|
||||
public string? Username { get; set; }
|
||||
|
||||
public string? Password { get; set; }
|
||||
|
||||
public string? Domain { get; set; }
|
||||
|
||||
public string? Workstation { get; set; }
|
||||
|
||||
public string? AddedWho { get; set; }
|
||||
|
||||
public DateTime? AddedWhen { get; set; }
|
||||
|
||||
public string? ChangedWho { get; set; }
|
||||
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the TBREC_CFG_ENDPOINT_PARAMS table.
|
||||
/// All properties are nullable to provide flexibility on the database side,
|
||||
/// preventing breaking changes if columns are altered to be nullable in production.
|
||||
/// </summary>
|
||||
[Table("TBREC_CFG_ENDPOINT_PARAMS", Schema = "dbo")]
|
||||
public class EndpointParam
|
||||
{
|
||||
public long? Id { get; set; }
|
||||
|
||||
public bool? Active { get; set; }
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public short? GroupId { get; set; }
|
||||
|
||||
public byte? Sequence { get; set; }
|
||||
|
||||
public string? Key { get; set; }
|
||||
|
||||
public string? Value { get; set; }
|
||||
|
||||
public string? AddedWho { get; set; }
|
||||
|
||||
public DateTime? AddedWhen { get; set; }
|
||||
|
||||
public string? ChangedWho { get; set; }
|
||||
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Domain.Entities;
|
||||
|
||||
[Table("TBREC_OUT_RESULT", Schema = "dbo")]
|
||||
public class OutRes
|
||||
{
|
||||
public long? Id { get; set; }
|
||||
|
||||
public long? ActionId { get; set; }
|
||||
|
||||
public RecAction? Action { get; set; }
|
||||
|
||||
public short? Status { get; set; }
|
||||
|
||||
public string? Header { get; set; }
|
||||
|
||||
public string? Body { get; set; }
|
||||
|
||||
public string? AddedWho { get; set; }
|
||||
|
||||
public DateTime? AddedWhen { get; set; }
|
||||
|
||||
public string? ChangedWho { get; set; }
|
||||
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Domain.Entities;
|
||||
|
||||
[Table("TBREC_CFG_PROFILE", Schema = "dbo")]
|
||||
public class Profile
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public bool? Active { get; set; }
|
||||
|
||||
public string? Type { get; set; }
|
||||
|
||||
public string? Mandantor { get; set; }
|
||||
|
||||
public string? Name { get; set; }
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public string? LogLevel { get; set; }
|
||||
|
||||
public string? Language { get; set; }
|
||||
|
||||
public string? AddedWho { get; set; }
|
||||
|
||||
public DateTime? AddedWhen { get; set; }
|
||||
|
||||
public string? ChangedWho { get; set; }
|
||||
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
using ReC.Domain.Constants;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Domain.Entities;
|
||||
|
||||
[Table("TBREC_CFG_ACTION")]
|
||||
public class RecAction
|
||||
{
|
||||
public long? Id { get; set; }
|
||||
|
||||
public long? ProfileId { get; set; }
|
||||
|
||||
public Profile? Profile { get; set; }
|
||||
|
||||
public bool? Active { get; set; }
|
||||
|
||||
public byte? Sequence { get; set; }
|
||||
|
||||
public long? EndpointId { get; set; }
|
||||
|
||||
public Endpoint? Endpoint { get; set; }
|
||||
|
||||
public long? EndpointAuthId { get; set; }
|
||||
|
||||
public EndpointAuth? EndpointAuth { get; set; }
|
||||
|
||||
public short? EndpointParamsId { get; set; }
|
||||
|
||||
public short? SqlConnectionId { get; set; }
|
||||
|
||||
public Connection? SqlConnection { get; set; }
|
||||
|
||||
public string? Type { get; set; }
|
||||
|
||||
public string? PreprocessingQuery { get; set; }
|
||||
|
||||
public string? HeaderQuery { get; set; }
|
||||
|
||||
public string? BodyQuery { get; set; }
|
||||
|
||||
public string? PostprocessingQuery { get; set; }
|
||||
|
||||
public ErrorAction? ErrorAction { get; set; }
|
||||
|
||||
public string? AddedWho { get; set; }
|
||||
|
||||
public DateTime? AddedWhen { get; set; }
|
||||
|
||||
public string? ChangedWho { get; set; }
|
||||
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
|
||||
public OutRes? OutRes { get; set; }
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ReC.Domain.Entities;
|
||||
namespace ReC.Domain.QueryOutput;
|
||||
|
||||
public class BodyQueryResult
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ReC.Domain.Entities;
|
||||
namespace ReC.Domain.QueryOutput;
|
||||
|
||||
public class HeaderQueryResult
|
||||
{
|
||||
8
src/ReC.Domain/QueryOutput/InsertObjectResult.cs
Normal file
8
src/ReC.Domain/QueryOutput/InsertObjectResult.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Domain.QueryOutput;
|
||||
|
||||
public class InsertObjectResult
|
||||
{
|
||||
public required long NewObjectId { get; set; }
|
||||
}
|
||||
@@ -6,6 +6,8 @@ namespace ReC.Domain.Views;
|
||||
[Table("VWREC_PROFILE", Schema = "dbo")]
|
||||
public record ProfileView
|
||||
{
|
||||
public virtual IEnumerable<RecActionView>? Actions { get; init; }
|
||||
|
||||
public long Id { get; init; }
|
||||
|
||||
public bool Active { get; init; }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using ReC.Domain.Constants;
|
||||
using ReC.Domain.Entities;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ReC.Domain.Views;
|
||||
@@ -15,10 +14,9 @@ namespace ReC.Domain.Views;
|
||||
[Table("VWREC_ACTION", Schema = "dbo")]
|
||||
public class RecActionView
|
||||
{
|
||||
public required long Id { get; set; }
|
||||
public virtual IEnumerable<ResultView>? Results { get; set; }
|
||||
|
||||
[ForeignKey("Id")]
|
||||
public RecAction? Root { get; set; }
|
||||
public required long Id { get; set; }
|
||||
|
||||
public long? ProfileId { get; set; }
|
||||
|
||||
@@ -33,16 +31,10 @@ public class RecActionView
|
||||
|
||||
public long? EndpointId { get; set; }
|
||||
|
||||
[ForeignKey("EndpointId")]
|
||||
public Endpoint? Endpoint { get; set; }
|
||||
|
||||
public string? EndpointUri { get; set; }
|
||||
|
||||
public long? EndpointAuthId { get; set; }
|
||||
|
||||
[ForeignKey("EndpointAuthId")]
|
||||
public EndpointAuth? EndpointAuth { get; set; }
|
||||
|
||||
public EndpointAuthType? EndpointAuthType { get; set; }
|
||||
|
||||
public string? EndpointAuthTypeName { get; set; }
|
||||
@@ -69,9 +61,6 @@ public class RecActionView
|
||||
|
||||
public short? SqlConnectionId { get; set; }
|
||||
|
||||
[ForeignKey("SqlConnectionId")]
|
||||
public Connection? SqlConnection { get; set; }
|
||||
|
||||
public string? SqlConnectionServer { get; set; }
|
||||
|
||||
public string? SqlConnectionDb { get; set; }
|
||||
|
||||
@@ -23,7 +23,11 @@ public static class DependencyInjection
|
||||
|
||||
services.AddScoped<IRecDbContext>(provider => provider.GetRequiredService<TRecDbContext>());
|
||||
|
||||
services.AddDbRepository(opt => opt.RegisterFromAssembly<TRecDbContext>(typeof(RecActionView).Assembly));
|
||||
services.AddDbRepository(opt =>
|
||||
{
|
||||
opt.RegisterFromAssembly<TRecDbContext>(typeof(RecActionView).Assembly);
|
||||
opt.RegisterDefaultRepository<TRecDbContext>();
|
||||
});
|
||||
|
||||
services.AddValidatorsFromAssembly(typeof(AuthScopedValidator).Assembly);
|
||||
|
||||
|
||||
@@ -1,229 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ReC.Application.Common.Interfaces;
|
||||
using ReC.Domain.Entities;
|
||||
using ReC.Domain.QueryOutput;
|
||||
using ReC.Domain.Views;
|
||||
|
||||
namespace ReC.Infrastructure;
|
||||
|
||||
public class RecDbContext(DbContextOptions<RecDbContext> options) : DbContext(options), IRecDbContext
|
||||
{
|
||||
public DbSet<EndpointParam> EndpointParams { get; set; }
|
||||
|
||||
#region DB Sets
|
||||
public DbSet<RecActionView> RecActionViews { get; set; }
|
||||
|
||||
public DbSet<ProfileView> ProfileViews { get; set; }
|
||||
|
||||
public DbSet<ResultView> RecResultViews { get; set; }
|
||||
|
||||
public DbSet<OutRes> OutRes { get; set; }
|
||||
|
||||
public DbSet<HeaderQueryResult> HeaderQueryResults { get; set; }
|
||||
|
||||
public DbSet<BodyQueryResult> BodyQueryResults { get; set; }
|
||||
|
||||
public DbSet<Connection> Connections { get; set; }
|
||||
|
||||
public DbSet<Endpoint> Endpoints { get; set; }
|
||||
|
||||
public DbSet<EndpointAuth> EndpointAuths { get; set; }
|
||||
|
||||
public DbSet<Profile> Profiles { get; set; }
|
||||
|
||||
public DbSet<RecAction> RecActions { get; set; }
|
||||
public DbSet<InsertObjectResult> RecResults { get; set; }
|
||||
#endregion DB Sets
|
||||
|
||||
// TODO: Update to configure via appsettings.json
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<Connection>(b =>
|
||||
{
|
||||
b.ToTable("TBDD_CONNECTION");
|
||||
|
||||
b.HasKey(e => e.Id);
|
||||
|
||||
b.Property(e => e.Id)
|
||||
.HasColumnName("GUID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property(e => e.Bezeichnung).HasColumnName("BEZEICHNUNG");
|
||||
b.Property(e => e.SqlProvider).HasColumnName("SQL_PROVIDER");
|
||||
b.Property(e => e.Server).HasColumnName("SERVER");
|
||||
b.Property(e => e.Datenbank).HasColumnName("DATENBANK");
|
||||
b.Property(e => e.Username).HasColumnName("USERNAME");
|
||||
b.Property(e => e.Password).HasColumnName("PASSWORD");
|
||||
b.Property(e => e.Bemerkung).HasColumnName("BEMERKUNG");
|
||||
b.Property(e => e.Aktiv).HasColumnName("AKTIV");
|
||||
b.Property(e => e.ErstelltWer).HasColumnName("ERSTELLTWER");
|
||||
b.Property(e => e.ErstelltWann).HasColumnName("ERSTELLTWANN");
|
||||
b.Property(e => e.GeandertWer).HasColumnName("GEANDERTWER");
|
||||
b.Property(e => e.GeaendertWann).HasColumnName("GEAENDERTWANN");
|
||||
b.Property(e => e.SysConnection).HasColumnName("SYS_CONNECTION");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Endpoint>(b =>
|
||||
{
|
||||
b.ToTable("TBREC_CFG_ENDPOINT");
|
||||
|
||||
b.HasKey(e => e.Id);
|
||||
|
||||
b.Property(e => e.Id)
|
||||
.HasColumnName("GUID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property(e => e.Active).HasColumnName("ACTIVE");
|
||||
b.Property(e => e.Description).HasColumnName("DESCRIPTION");
|
||||
b.Property(e => e.Uri).HasColumnName("URI");
|
||||
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
|
||||
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
|
||||
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
|
||||
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<EndpointAuth>(b =>
|
||||
{
|
||||
b.ToTable("TBREC_CFG_ENDPOINT_AUTH");
|
||||
|
||||
b.HasKey(e => e.Id);
|
||||
|
||||
b.Property(e => e.Id)
|
||||
.HasColumnName("GUID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property(e => e.Active).HasColumnName("ACTIVE");
|
||||
b.Property(e => e.Description).HasColumnName("DESCRIPTION");
|
||||
b.Property(e => e.Type).HasColumnName("TYPE");
|
||||
b.Property(e => e.ApiKey).HasColumnName("API_KEY");
|
||||
b.Property(e => e.ApiValue).HasColumnName("API_VALUE");
|
||||
b.Property(e => e.ApiKeyAddTo).HasColumnName("API_KEY_ADD_TO");
|
||||
b.Property(e => e.Token).HasColumnName("TOKEN");
|
||||
b.Property(e => e.Username).HasColumnName("USERNAME");
|
||||
b.Property(e => e.Password).HasColumnName("PASSWORD");
|
||||
b.Property(e => e.Domain).HasColumnName("DOMAIN");
|
||||
b.Property(e => e.Workstation).HasColumnName("WORKSTATION");
|
||||
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
|
||||
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
|
||||
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
|
||||
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<EndpointParam>(b =>
|
||||
{
|
||||
b.ToTable("TBREC_CFG_ENDPOINT_PARAMS", "dbo");
|
||||
|
||||
b.HasKey(e => e.Id);
|
||||
|
||||
b.Property(e => e.Id).HasColumnName("GUID");
|
||||
b.Property(e => e.Active).HasColumnName("ACTIVE");
|
||||
b.Property(e => e.Description).HasColumnName("DESCRIPTION");
|
||||
b.Property(e => e.GroupId).HasColumnName("GROUP_ID");
|
||||
b.Property(e => e.Sequence).HasColumnName("SEQUENCE");
|
||||
b.Property(e => e.Key).HasColumnName("KEY");
|
||||
b.Property(e => e.Value).HasColumnName("VALUE");
|
||||
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
|
||||
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
|
||||
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
|
||||
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<OutRes>(b =>
|
||||
{
|
||||
b.ToTable("TBREC_OUT_RESULT", "dbo");
|
||||
|
||||
b.HasKey(e => e.Id);
|
||||
|
||||
b.Property(e => e.Id)
|
||||
.HasColumnName("GUID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property(e => e.ActionId).HasColumnName("ACTION_ID");
|
||||
b.Property(e => e.Status).HasColumnName("STATUS_ID");
|
||||
b.Property(e => e.Header).HasColumnName("RESULT_HEADER");
|
||||
b.Property(e => e.Body).HasColumnName("RESULT_BODY");
|
||||
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
|
||||
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
|
||||
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
|
||||
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Profile>(b =>
|
||||
{
|
||||
b.ToTable("TBREC_CFG_PROFILE", "dbo");
|
||||
|
||||
b.HasKey(e => e.Id);
|
||||
|
||||
b.Property(e => e.Id)
|
||||
.HasColumnName("GUID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property(e => e.Active).HasColumnName("ACTIVE");
|
||||
b.Property(e => e.Type).HasColumnName("TYPE");
|
||||
b.Property(e => e.Mandantor).HasColumnName("MANDANTOR");
|
||||
b.Property(e => e.Name).HasColumnName("PROFILE_NAME");
|
||||
b.Property(e => e.Description).HasColumnName("DESCRIPTION");
|
||||
b.Property(e => e.LogLevel).HasColumnName("LOG_LEVEL");
|
||||
b.Property(e => e.Language).HasColumnName("LANGUAGE");
|
||||
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
|
||||
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
|
||||
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
|
||||
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<ProfileView>(b =>
|
||||
{
|
||||
b.ToView("VWREC_PROFILE", "dbo");
|
||||
b.HasKey(e => e.Id);
|
||||
|
||||
b.Property(e => e.Id).HasColumnName("PROFILE_GUID");
|
||||
b.Property(e => e.Active).HasColumnName("ACTIVE");
|
||||
b.Property(e => e.TypeId).HasColumnName("TYPE_ID");
|
||||
b.Property(e => e.Type).HasColumnName("TYPE");
|
||||
b.Property(e => e.Mandantor).HasColumnName("MANDANTOR");
|
||||
b.Property(e => e.ProfileName).HasColumnName("PROFILE_NAME");
|
||||
b.Property(e => e.Description).HasColumnName("DESCRIPTION");
|
||||
b.Property(e => e.LogLevelId).HasColumnName("LOG_LEVEL_ID");
|
||||
b.Property(e => e.LogLevel).HasColumnName("LOG_LEVEL");
|
||||
b.Property(e => e.LanguageId).HasColumnName("LANGUAGE_ID");
|
||||
b.Property(e => e.Language).HasColumnName("LANGUAGE");
|
||||
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
|
||||
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
|
||||
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
|
||||
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
|
||||
b.Property(e => e.FirstRun).HasColumnName("FIRST_RUN");
|
||||
b.Property(e => e.LastRun).HasColumnName("LAST_RUN");
|
||||
b.Property(e => e.LastResult).HasColumnName("LAST_RESULT");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RecAction>(b =>
|
||||
{
|
||||
b.ToTable("TBREC_CFG_ACTION");
|
||||
|
||||
b.HasKey(e => e.Id);
|
||||
|
||||
b.Property(e => e.Id).HasColumnName("GUID");
|
||||
b.Property(e => e.ProfileId).HasColumnName("PROFILE_ID");
|
||||
b.Property(e => e.Active).HasColumnName("ACTIVE");
|
||||
b.Property(e => e.Sequence).HasColumnName("SEQUENCE");
|
||||
b.Property(e => e.EndpointId).HasColumnName("ENDPOINT_ID");
|
||||
b.Property(e => e.EndpointAuthId).HasColumnName("ENDPOINT_AUTH_ID");
|
||||
b.Property(e => e.EndpointParamsId).HasColumnName("ENDPOINT_PARAMS_ID");
|
||||
b.Property(e => e.SqlConnectionId).HasColumnName("SQL_CONNECTION_ID");
|
||||
b.Property(e => e.Type).HasColumnName("TYPE");
|
||||
b.Property(e => e.PreprocessingQuery).HasColumnName("PREPROCESSING_QUERY");
|
||||
b.Property(e => e.HeaderQuery).HasColumnName("HEADER_QUERY");
|
||||
b.Property(e => e.BodyQuery).HasColumnName("BODY_QUERY");
|
||||
b.Property(e => e.PostprocessingQuery).HasColumnName("POSTPROCESSING_QUERY");
|
||||
b.Property(e => e.ErrorAction).HasColumnName("ERROR_ACTION");
|
||||
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
|
||||
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
|
||||
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
|
||||
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
|
||||
|
||||
b.HasOne(act => act.OutRes)
|
||||
.WithOne(res => res.Action)
|
||||
.HasForeignKey<OutRes>(res => res.ActionId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RecActionView>(b =>
|
||||
{
|
||||
b.ToView("VWREC_ACTION", "dbo");
|
||||
@@ -262,6 +64,34 @@ public class RecDbContext(DbContextOptions<RecDbContext> options) : DbContext(op
|
||||
b.Property(e => e.PostprocessingQuery).HasColumnName("POSTPROCESSING_QUERY");
|
||||
b.Property(e => e.ErrorAction).HasColumnName("ERROR_ACTION_ID");
|
||||
b.Property(e => e.ErrorActionName).HasColumnName("ERROR_ACTION");
|
||||
|
||||
b.HasMany(e => e.Results)
|
||||
.WithOne(r => r.Action)
|
||||
.HasForeignKey(r => r.ActionId);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<ProfileView>(b =>
|
||||
{
|
||||
b.ToView("VWREC_PROFILE", "dbo");
|
||||
b.HasKey(e => e.Id);
|
||||
b.Property(e => e.Id).HasColumnName("PROFILE_GUID");
|
||||
b.Property(e => e.Active).HasColumnName("ACTIVE");
|
||||
b.Property(e => e.TypeId).HasColumnName("TYPE_ID");
|
||||
b.Property(e => e.Type).HasColumnName("TYPE");
|
||||
b.Property(e => e.Mandantor).HasColumnName("MANDANTOR");
|
||||
b.Property(e => e.ProfileName).HasColumnName("PROFILE_NAME");
|
||||
b.Property(e => e.Description).HasColumnName("DESCRIPTION");
|
||||
b.Property(e => e.LogLevelId).HasColumnName("LOG_LEVEL_ID");
|
||||
b.Property(e => e.LogLevel).HasColumnName("LOG_LEVEL");
|
||||
b.Property(e => e.LanguageId).HasColumnName("LANGUAGE_ID");
|
||||
b.Property(e => e.Language).HasColumnName("LANGUAGE");
|
||||
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
|
||||
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
|
||||
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
|
||||
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
|
||||
b.Property(e => e.FirstRun).HasColumnName("FIRST_RUN");
|
||||
b.Property(e => e.LastRun).HasColumnName("LAST_RUN");
|
||||
b.Property(e => e.LastResult).HasColumnName("LAST_RESULT");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<ResultView>(b =>
|
||||
@@ -281,6 +111,14 @@ public class RecDbContext(DbContextOptions<RecDbContext> options) : DbContext(op
|
||||
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
|
||||
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
|
||||
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
|
||||
|
||||
b.HasOne(r => r.Action)
|
||||
.WithMany(a => a.Results)
|
||||
.HasForeignKey(r => r.ActionId);
|
||||
|
||||
b.HasOne(r => r.Profile)
|
||||
.WithMany()
|
||||
.HasForeignKey(r => r.ProfileId);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<HeaderQueryResult>(b =>
|
||||
@@ -295,5 +133,10 @@ public class RecDbContext(DbContextOptions<RecDbContext> options) : DbContext(op
|
||||
b.Property(e => e.RawBody).HasColumnName("REQUEST_BODY");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<InsertObjectResult>(b =>
|
||||
{
|
||||
b.HasNoKey();
|
||||
b.Property(e => e.NewObjectId).HasColumnName("oGUID");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Threading.Tasks;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.EndpointAuth.Commands;
|
||||
using ReC.Tests.Application;
|
||||
|
||||
namespace ReC.Tests.Application.EndpointAuth;
|
||||
|
||||
[TestFixture]
|
||||
public class EndpointAuthProcedureTests : RecApplicationTestBase
|
||||
{
|
||||
private (ISender Sender, IServiceScope Scope) CreateScopedSender()
|
||||
{
|
||||
var scope = ServiceProvider.CreateScope();
|
||||
var sender = scope.ServiceProvider.GetRequiredService<ISender>();
|
||||
return (sender, scope);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task InsertEndpointAuthProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new InsertEndpointAuthProcedure { Active = true, Description = "auth", TypeId = 1, ApiKey = "key", ApiValue = "value" };
|
||||
var objectProc = procedure.ToObjectProcedure("ReC.Tests");
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.GreaterThan(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task UpdateEndpointAuthProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new UpdateEndpointAuthProcedure { Active = false, Description = "auth-update", TypeId = 2 };
|
||||
var objectProc = procedure.ToObjectProcedure(15, "ReC.Tests");
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.Not.EqualTo(default(int)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DeleteEndpointAuthProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new DeleteEndpointAuthProcedure { Start = 3, End = 4, Force = false };
|
||||
var objectProc = procedure.ToObjectProcedure();
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.Not.EqualTo(default(int)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Threading.Tasks;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.EndpointParams.Commands;
|
||||
using ReC.Tests.Application;
|
||||
|
||||
namespace ReC.Tests.Application.EndpointParams;
|
||||
|
||||
[TestFixture]
|
||||
public class EndpointParamsProcedureTests : RecApplicationTestBase
|
||||
{
|
||||
private (ISender Sender, IServiceScope Scope) CreateScopedSender()
|
||||
{
|
||||
var scope = ServiceProvider.CreateScope();
|
||||
var sender = scope.ServiceProvider.GetRequiredService<ISender>();
|
||||
return (sender, scope);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task InsertEndpointParamsProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new InsertEndpointParamsProcedure { Active = true, Description = "param", GroupId = 1, Sequence = 1, Key = "k", Value = "v" };
|
||||
var objectProc = procedure.ToObjectProcedure("ReC.Tests");
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.GreaterThan(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task UpdateEndpointParamsProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new UpdateEndpointParamsProcedure { Active = false, Description = "param-update", GroupId = 2, Sequence = 2, Key = "k2", Value = "v2" };
|
||||
var objectProc = procedure.ToObjectProcedure(25, "ReC.Tests");
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.Not.EqualTo(default(int)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DeleteEndpointParamsProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new DeleteEndpointParamsProcedure { Start = 5, End = 6, Force = true };
|
||||
var objectProc = procedure.ToObjectProcedure();
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.Not.EqualTo(default(int)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Threading.Tasks;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.Endpoints.Commands;
|
||||
using ReC.Tests.Application;
|
||||
|
||||
namespace ReC.Tests.Application.Endpoints;
|
||||
|
||||
[TestFixture]
|
||||
public class EndpointProcedureTests : RecApplicationTestBase
|
||||
{
|
||||
private (ISender Sender, IServiceScope Scope) CreateScopedSender()
|
||||
{
|
||||
var scope = ServiceProvider.CreateScope();
|
||||
var sender = scope.ServiceProvider.GetRequiredService<ISender>();
|
||||
return (sender, scope);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task InsertEndpointProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new InsertEndpointProcedure { Active = true, Description = "desc", Uri = "http://example" };
|
||||
var objectProc = procedure.ToObjectProcedure("ReC.Tests");
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.GreaterThan(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task UpdateEndpointProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new UpdateEndpointProcedure { Active = false, Description = "updated", Uri = "http://updated" };
|
||||
var objectProc = procedure.ToObjectProcedure(12, "ReC.Tests");
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.Not.EqualTo(default(int)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DeleteEndpointProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new DeleteEndpointProcedure { Start = 1, End = 2, Force = true };
|
||||
var objectProc = procedure.ToObjectProcedure();
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.Not.EqualTo(default(int)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Threading.Tasks;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.Profile.Commands;
|
||||
using ReC.Tests.Application;
|
||||
|
||||
namespace ReC.Tests.Application.Procedures;
|
||||
|
||||
[TestFixture]
|
||||
public class ProcedureExecutionTests : RecApplicationTestBase
|
||||
{
|
||||
private (ISender Sender, IServiceScope Scope) CreateScopedSender()
|
||||
{
|
||||
var scope = ServiceProvider.CreateScope();
|
||||
var sender = scope.ServiceProvider.GetRequiredService<ISender>();
|
||||
return (sender, scope);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteInsertProcedure_runs_with_addedWho()
|
||||
{
|
||||
var procedure = new InsertProfileProcedure { Name = "name" };
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.ExecuteInsertProcedure(procedure, "ReC.Tests");
|
||||
|
||||
Assert.That(result, Is.GreaterThan(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteUpdateProcedure_runs_with_changedWho()
|
||||
{
|
||||
var procedure = new UpdateProfileProcedure { Name = "updated" };
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.ExecuteUpdateProcedure(procedure, 123, "ReC.Tests");
|
||||
|
||||
Assert.That(result, Is.Not.EqualTo(default(int)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteDeleteProcedure_runs()
|
||||
{
|
||||
var procedure = new DeleteProfileProcedure { Start = 1, End = 2, Force = true };
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.ExecuteDeleteProcedure(procedure);
|
||||
|
||||
Assert.That(result, Is.Not.EqualTo(default(int)));
|
||||
}
|
||||
}
|
||||
61
tests/ReC.Tests/Application/Profile/ProfileProcedureTests.cs
Normal file
61
tests/ReC.Tests/Application/Profile/ProfileProcedureTests.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System.Threading.Tasks;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using ReC.Application.Common.Procedures.DeleteProcedure;
|
||||
using ReC.Application.Common.Procedures.InsertProcedure;
|
||||
using ReC.Application.Common.Procedures.UpdateProcedure;
|
||||
using ReC.Application.Profile.Commands;
|
||||
using ReC.Tests.Application;
|
||||
|
||||
namespace ReC.Tests.Application.Profile;
|
||||
|
||||
[TestFixture]
|
||||
public class ProfileProcedureTests : RecApplicationTestBase
|
||||
{
|
||||
private (ISender Sender, IServiceScope Scope) CreateScopedSender()
|
||||
{
|
||||
var scope = ServiceProvider.CreateScope();
|
||||
var sender = scope.ServiceProvider.GetRequiredService<ISender>();
|
||||
return (sender, scope);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task InsertProfileProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new InsertProfileProcedure { Active = true, TypeId = 1, Name = "name", Mandantor = "man" };
|
||||
var objectProc = procedure.ToObjectProcedure("ReC.Tests");
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.GreaterThan(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task UpdateProfileProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new UpdateProfileProcedure { Active = false, TypeId = 2, Name = "updated", Mandantor = "man2" };
|
||||
var objectProc = procedure.ToObjectProcedure(45, "ReC.Tests");
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.Not.EqualTo(default(int)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DeleteProfileProcedure_runs_via_mediator()
|
||||
{
|
||||
var procedure = new DeleteProfileProcedure { Start = 9, End = 10, Force = false };
|
||||
var objectProc = procedure.ToObjectProcedure();
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
var result = await sender.Send(objectProc);
|
||||
|
||||
Assert.That(result, Is.Not.EqualTo(default(int)));
|
||||
}
|
||||
}
|
||||
51
tests/ReC.Tests/Application/Profile/ProfileQueryTests.cs
Normal file
51
tests/ReC.Tests/Application/Profile/ProfileQueryTests.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using ReC.Application.Profile.Queries;
|
||||
using ReC.Tests.Application;
|
||||
|
||||
namespace ReC.Tests.Application.Profile;
|
||||
|
||||
[TestFixture]
|
||||
public class ProfileQueryTests : RecApplicationTestBase
|
||||
{
|
||||
private (ISender Sender, IServiceScope Scope) CreateScopedSender()
|
||||
{
|
||||
var scope = ServiceProvider.CreateScope();
|
||||
var sender = scope.ServiceProvider.GetRequiredService<ISender>();
|
||||
return (sender, scope);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ReadProfileViewQuery_returns_profile_from_database()
|
||||
{
|
||||
var profileId = Configuration.GetValue<long?>("FakeProfileId");
|
||||
Assert.That(profileId, Is.Not.Null.And.GreaterThan(0), "FakeProfileId must be configured in appsettings.json");
|
||||
|
||||
var (sender, scope) = CreateScopedSender();
|
||||
using var _ = scope;
|
||||
|
||||
try
|
||||
{
|
||||
var profiles = await sender.Send(new ReadProfileViewQuery
|
||||
{
|
||||
Id = profileId,
|
||||
IncludeActions = false
|
||||
});
|
||||
|
||||
var profile = profiles.Single();
|
||||
|
||||
Assert.That(profile.Id, Is.EqualTo(profileId));
|
||||
Assert.That(profile.ProfileName, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(profile.Active, Is.True);
|
||||
}
|
||||
catch (NotFoundException)
|
||||
{
|
||||
Assert.Pass("NotFound is acceptable when profile does not exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user