using CMSDAL.CustomCode.ContentContainer; using CMSDAL.DTO.ContentContainer; using GB5Shared.DTO.Framework.Login; using GB5Shared.Validation; namespace FrameworkBLL.ContentContainer; public class ContentContainerBLL : CMSBLL.ContentContainer.IContentContainerBLL { private readonly IContentContainerDAL _dal; private readonly ICrossTenantGuard _guard; public ContentContainerBLL(IContentContainerDAL dal, ICrossTenantGuard guard) { _dal = dal; _guard = guard; } public async Task GetByContentAsync(int contentId, LoginDTO loginDTO, CancellationToken ct) { try { return await _dal.GetByContentAsync(contentId, loginDTO, ct); } catch { throw; } } public async Task SaveAsync(ContentContainerDTO dto, LoginDTO loginDTO, CancellationToken ct) { try { // Only a brand-new container attaches to a caller-supplied ContentId — an update to // an existing container is already tenant-scoped by ContentContainerQB.UPDATE_POSITION's // own WHERE clause. Without this check, any tenant could attach a container to another // tenant's Content row simply by guessing its ContentId. if (dto.ContentContainerId == 0) { var ownerTenantId = await _dal.GetContentTenantIdAsync(dto.ContentId, loginDTO, ct); _guard.EnsureOwnedByTenant(ownerTenantId, loginDTO.ClientId, "Content", dto.ContentId); } return await _dal.SaveAsync(dto, loginDTO, ct); } catch { throw; } } public async Task ReorderAsync(int contentContainerId, short positionNo, LoginDTO loginDTO, CancellationToken ct) { try { return await _dal.ReorderAsync(contentContainerId, positionNo, loginDTO, ct); } catch { throw; } } public async Task DeleteAsync(int contentContainerId, LoginDTO loginDTO, CancellationToken ct) { try { return await _dal.DeleteAsync(contentContainerId, loginDTO, ct); } catch { throw; } } }