Files
sockeye/server/biz/IntegrationBiz.cs
2022-12-16 06:01:23 +00:00

254 lines
9.1 KiB
C#

using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Sockeye.Util;
using Sockeye.Api.ControllerHelpers;
using Sockeye.Models;
using System.Linq;
using System.Collections.Generic;
namespace Sockeye.Biz
{
internal class IntegrationBiz : BizObject
{
/*
todo: needs code to back routes for logging and fetching log to view
*/
internal IntegrationBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
{
ct = dbcontext;
UserId = currentUserId;
UserTranslationId = userTranslationId;
CurrentUserRoles = UserRoles;
BizType = SockType.Integration;
}
internal static IntegrationBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null)
{
if (httpContext != null)
return new IntegrationBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items));
else
return new IntegrationBiz(ct, 1, ServerBootConfig.SOCKEYE_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdmin);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//EXISTS
internal async Task<bool> ExistsAsync(long id)
{
return await ct.Integration.AnyAsync(z => z.Id == id);
}
internal async Task<bool> ExistsByIntegrationAppIdAsync(Guid IntegrationAppId)
{
return await ct.Integration.AnyAsync(z => z.IntegrationAppId == IntegrationAppId);
}
///////////////////////////////////////////////////////
//APPID FROM dbID
internal async Task<Guid> AppIdFromDbIdAsync(long id)
{
return await ct.Integration.AsNoTracking().Where(z => z.Id == id).Select(z => z.IntegrationAppId).SingleOrDefaultAsync();
}
////////////////////////////////////////////////////////////////////////////////////////////////
//CREATE
//
internal async Task<Integration> CreateAsync(Integration newObject)
{
await ValidateAsync(newObject, null);
if (HasErrors)
return null;
else
{
await ct.Integration.AddAsync(newObject);
await ct.SaveChangesAsync();
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, SockEvent.Created), ct);
return newObject;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
//GET
//
internal async Task<Integration> GetAsync(long id, bool logTheGetEvent = true)
{
return await GetAsync(await AppIdFromDbIdAsync(id), logTheGetEvent);
}
internal async Task<Integration> GetAsync(Guid IntegrationAppId, bool logTheGetEvent = true)
{
var ret = await ct.Integration.AsNoTracking().Include(z => z.Items).SingleOrDefaultAsync(m => m.IntegrationAppId == IntegrationAppId);
if (logTheGetEvent && ret != null)
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, ret.Id, BizType, SockEvent.Retrieved), ct);
return ret;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//UPDATE
//
internal async Task<Integration> PutAsync(Integration putObject)
{
//Get the db object with no tracking as about to be replaced not updated
Integration dbObject = await GetAsync(putObject.IntegrationAppId, false);
if (dbObject == null)
{
AddError(ApiErrorCode.NOT_FOUND, "IntegrationAppId");
return null;
}
if (dbObject.Concurrency != putObject.Concurrency)
{
AddError(ApiErrorCode.CONCURRENCY_CONFLICT);
return null;
}
await ValidateAsync(putObject, dbObject);
if (HasErrors) return null;
ct.Replace(dbObject, putObject);
try
{
await ct.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!await ExistsAsync(putObject.Id))
AddError(ApiErrorCode.NOT_FOUND);
else
AddError(ApiErrorCode.CONCURRENCY_CONFLICT);
return null;
}
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, SockEvent.Modified), ct);
return putObject;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE
//
internal async Task<bool> DeleteAsync(long id)
{
return await DeleteAsync(await AppIdFromDbIdAsync(id));
}
internal async Task<bool> DeleteAsync(Guid IntegrationAppId)
{
using (var transaction = await ct.Database.BeginTransactionAsync())
{
Integration dbObject = await GetAsync(IntegrationAppId, false);
if (dbObject == null)
{
AddError(ApiErrorCode.NOT_FOUND);
return false;
}
ValidateCanDelete(dbObject);
if (HasErrors)
return false;
ct.Integration.Remove(dbObject);
await ct.SaveChangesAsync();
//Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await transaction.CommitAsync();
return true;
}
}
/////////////////////////////////////////////////////////////////////////////////
//LOG to integration log
//
internal async Task<bool> LogAsync(NameIdItem logItem)
{
if (string.IsNullOrWhiteSpace(logItem.Name))
{
AddError(ApiErrorCode.NOT_FOUND, "name", "The log text message (name) is empty, nothing to log");
return false;
}
if (!await ExistsAsync(logItem.Id))
{
AddError(ApiErrorCode.NOT_FOUND, "id", "The integration id specified was not found, remember this is the internal id (integer), not the application specific id (Guid)");
return false;
}
await ct.IntegrationLog.AddAsync(new IntegrationLog { IntegrationId = logItem.Id, StatusText = logItem.Name });
await ct.SaveChangesAsync();
return true;
}
//GET LOG
internal async Task<List<IntegrationLog>> GetLogAsync(long id)
{
return await ct.IntegrationLog.AsNoTracking().Where(z=>z.IntegrationId==id).OrderByDescending(z=>z.Created).ToListAsync();
}
////////////////////////////////////////////////////////////////////////////////////////////////
//VALIDATION
//
private async Task ValidateAsync(Integration proposedObj, Integration currentObj)
{
bool isNew = currentObj == null;
//Name required
if (string.IsNullOrWhiteSpace(proposedObj.Name))
AddError(ApiErrorCode.VALIDATION_REQUIRED, "Name");
//If name is otherwise OK, check that name is unique
if (!PropertyHasErrors("Name"))
{
//Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
if (await ct.Integration.AnyAsync(m => m.Name == proposedObj.Name && m.Id != proposedObj.Id))
{
AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
}
}
//Name required
if (proposedObj.IntegrationAppId == Guid.Empty)
AddError(ApiErrorCode.VALIDATION_REQUIRED, "IntegrationAppId");
//If name is otherwise OK, check that name is unique
if (!PropertyHasErrors("IntegrationAppId"))
{
//Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
if (await ct.Integration.AnyAsync(m => m.IntegrationAppId == proposedObj.IntegrationAppId && m.Id != proposedObj.Id))
{
AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "IntegrationAppId");
}
}
}
private void ValidateCanDelete(Integration inObj)
{
//whatever needs to be check to delete this object
}
/////////////////////////////////////////////////////////////////////
}//eoc
}//eons