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.Common.Procedures.UpdateProcedure.Dto; using System.Text; namespace ReC.Application.Common.Procedures.UpdateProcedure; public record UpdateObjectProcedure : IRequest { /// /// Target entity: ACTION, ENDPOINT, ENDPOINT_AUTH, ENDPOINT_PARAMS, PROFILE, RESULT /// public string Entity { get; set; } = null!; /// /// Target GUID to update (required) /// public long Id { get; set; } //TODO: update to set in authentication middleware or similar, and remove from procedure properties internal string? ChangedWho { get; private set; } = "ReC.API"; public UpdateActionDto Action { get; set; } = new(); public UpdateEndpointDto Endpoint { get; set; } = new(); public UpdateEndpointAuthDto EndpointAuth { get; set; } = new(); public UpdateProfileDto Profile { get; set; } = new(); public UpdateResultDto Result { get; set; } = new(); public UpdateEndpointParamsDto EndpointParams { get; set; } = new(); } public class UpdateObjectProcedureHandler(IRepository repo, IOptionsMonitor sqlExOpt) : IRequestHandler { public async Task 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", System.Data.SqlDbType.TinyInt) { Value = (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", System.Data.SqlDbType.SmallInt) { Value = (object?)request.Action.EndpointParamsId ?? DBNull.Value }, new SqlParameter("@pACTION_SQL_CONNECTION_ID", System.Data.SqlDbType.SmallInt) { Value = (object?)request.Action.SqlConnectionId ?? DBNull.Value }, new SqlParameter("@pACTION_TYPE_ID", System.Data.SqlDbType.TinyInt) { Value = (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", System.Data.SqlDbType.TinyInt) { Value = (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", System.Data.SqlDbType.TinyInt) { Value = (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", System.Data.SqlDbType.SmallInt) { Value = (object?)request.EndpointParams.GroupId ?? DBNull.Value }, new SqlParameter("@pENDPOINT_PARAMS_SEQUENCE", System.Data.SqlDbType.TinyInt) { Value = (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", System.Data.SqlDbType.TinyInt) { Value = (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", System.Data.SqlDbType.TinyInt) { Value = (object?)request.Profile.LogLevelId ?? DBNull.Value }, new SqlParameter("@pPROFILE_LANGUAGE_ID", System.Data.SqlDbType.SmallInt) { Value = (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", System.Data.SqlDbType.SmallInt) { Value = (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 sql = new StringBuilder() .AppendLine("DECLARE @RC SMALLINT = 0;") .AppendLine("EXEC @RC = [dbo].[PRREC_UPDATE_OBJECT]") .AppendLine(" @pENTITY = @pENTITY,") .AppendLine(" @pGUID = @pGUID,") .AppendLine(" @pCHANGED_WHO = @pCHANGED_WHO,") .AppendLine(" @pCHANGED_WHEN = @pCHANGED_WHEN,") .AppendLine(" @pACTION_PROFILE_ID = @pACTION_PROFILE_ID,") .AppendLine(" @pACTION_ACTIVE = @pACTION_ACTIVE,") .AppendLine(" @pACTION_SEQUENCE = @pACTION_SEQUENCE,") .AppendLine(" @pACTION_ENDPOINT_ID = @pACTION_ENDPOINT_ID,") .AppendLine(" @pACTION_ENDPOINT_AUTH_ID = @pACTION_ENDPOINT_AUTH_ID,") .AppendLine(" @pACTION_ENDPOINT_PARAMS_ID = @pACTION_ENDPOINT_PARAMS_ID,") .AppendLine(" @pACTION_SQL_CONNECTION_ID = @pACTION_SQL_CONNECTION_ID,") .AppendLine(" @pACTION_TYPE_ID = @pACTION_TYPE_ID,") .AppendLine(" @pACTION_PRE_SQL = @pACTION_PRE_SQL,") .AppendLine(" @pACTION_HEADER_SQL = @pACTION_HEADER_SQL,") .AppendLine(" @pACTION_BODY_SQL = @pACTION_BODY_SQL,") .AppendLine(" @pACTION_POST_SQL = @pACTION_POST_SQL,") .AppendLine(" @pACTION_ERROR_ACTION_ID = @pACTION_ERROR_ACTION_ID,") .AppendLine(" @pENDPOINT_ACTIVE = @pENDPOINT_ACTIVE,") .AppendLine(" @pENDPOINT_DESCRIPTION = @pENDPOINT_DESCRIPTION,") .AppendLine(" @pENDPOINT_URI = @pENDPOINT_URI,") .AppendLine(" @pENDPOINT_AUTH_ACTIVE = @pENDPOINT_AUTH_ACTIVE,") .AppendLine(" @pENDPOINT_AUTH_DESCRIPTION = @pENDPOINT_AUTH_DESCRIPTION,") .AppendLine(" @pENDPOINT_AUTH_TYPE_ID = @pENDPOINT_AUTH_TYPE_ID,") .AppendLine(" @pENDPOINT_AUTH_API_KEY = @pENDPOINT_AUTH_API_KEY,") .AppendLine(" @pENDPOINT_AUTH_API_VALUE = @pENDPOINT_AUTH_API_VALUE,") .AppendLine(" @pENDPOINT_AUTH_API_KEY_ADD_TO_ID = @pENDPOINT_AUTH_API_KEY_ADD_TO_ID,") .AppendLine(" @pENDPOINT_AUTH_TOKEN = @pENDPOINT_AUTH_TOKEN,") .AppendLine(" @pENDPOINT_AUTH_USERNAME = @pENDPOINT_AUTH_USERNAME,") .AppendLine(" @pENDPOINT_AUTH_PASSWORD = @pENDPOINT_AUTH_PASSWORD,") .AppendLine(" @pENDPOINT_AUTH_DOMAIN = @pENDPOINT_AUTH_DOMAIN,") .AppendLine(" @pENDPOINT_AUTH_WORKSTATION = @pENDPOINT_AUTH_WORKSTATION,") .AppendLine(" @pENDPOINT_PARAMS_ACTIVE = @pENDPOINT_PARAMS_ACTIVE,") .AppendLine(" @pENDPOINT_PARAMS_DESCRIPTION = @pENDPOINT_PARAMS_DESCRIPTION,") .AppendLine(" @pENDPOINT_PARAMS_GROUP_ID = @pENDPOINT_PARAMS_GROUP_ID,") .AppendLine(" @pENDPOINT_PARAMS_SEQUENCE = @pENDPOINT_PARAMS_SEQUENCE,") .AppendLine(" @pENDPOINT_PARAMS_KEY = @pENDPOINT_PARAMS_KEY,") .AppendLine(" @pENDPOINT_PARAMS_VALUE = @pENDPOINT_PARAMS_VALUE,") .AppendLine(" @pPROFILE_ACTIVE = @pPROFILE_ACTIVE,") .AppendLine(" @pPROFILE_TYPE_ID = @pPROFILE_TYPE_ID,") .AppendLine(" @pPROFILE_MANDANTOR = @pPROFILE_MANDANTOR,") .AppendLine(" @pPROFILE_NAME = @pPROFILE_NAME,") .AppendLine(" @pPROFILE_DESCRIPTION = @pPROFILE_DESCRIPTION,") .AppendLine(" @pPROFILE_LOG_LEVEL_ID = @pPROFILE_LOG_LEVEL_ID,") .AppendLine(" @pPROFILE_LANGUAGE_ID = @pPROFILE_LANGUAGE_ID,") .AppendLine(" @pPROFILE_FIRST_RUN = @pPROFILE_FIRST_RUN,") .AppendLine(" @pPROFILE_LAST_RUN = @pPROFILE_LAST_RUN,") .AppendLine(" @pPROFILE_LAST_RESULT = @pPROFILE_LAST_RESULT,") .AppendLine(" @pRESULT_ACTION_ID = @pRESULT_ACTION_ID,") .AppendLine(" @pRESULT_STATUS_ID = @pRESULT_STATUS_ID,") .AppendLine(" @pRESULT_HEADER = @pRESULT_HEADER,") .AppendLine(" @pRESULT_BODY = @pRESULT_BODY;") .AppendLine("SELECT @RC;") .ToString(); var result = await repo.ExecuteQueryRawAsync(sql, 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; } } }