108 lines
4.6 KiB
C#
108 lines
4.6 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Tiku.Application.Catalog;
|
|
using Tiku.Application.Content;
|
|
using Tiku.Domain.Content;
|
|
using Tiku.Infrastructure.Security;
|
|
|
|
namespace Tiku.Infrastructure.Content;
|
|
|
|
public sealed partial class ContentManagementService
|
|
{
|
|
public async Task<CatalogList<ContentEntryManagementItem>> GetEntriesAsync(
|
|
ContentManagementActor actor,
|
|
ContentManagementFilter filter,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var scope = await RequireDataScopeAsync(actor, cancellationToken);
|
|
var regionIds = scope.RegionIds.ToArray();
|
|
var query = dbContext.ContentEntries
|
|
.AsNoTracking()
|
|
.Where(entry => entry.TenantId == actor.TenantId)
|
|
.ApplyDataScope(
|
|
scope,
|
|
entry => entry.CreatedBy == actor.UserId,
|
|
entry => entry.RegionId.HasValue && regionIds.Contains(entry.RegionId.Value));
|
|
|
|
if (!filter.IncludeInactive) query = query.Where(entry => entry.IsActive);
|
|
|
|
if (filter.RegionId.HasValue) query = query.Where(entry => entry.RegionId == filter.RegionId.Value);
|
|
|
|
if (TryParse(filter.EntryType, out ContentEntryType entryType))
|
|
query = query.Where(entry => entry.EntryType == entryType);
|
|
|
|
if (!string.IsNullOrWhiteSpace(filter.Keyword))
|
|
{
|
|
var keyword = filter.Keyword.Trim();
|
|
query = query.Where(entry =>
|
|
entry.Name.Contains(keyword) ||
|
|
entry.EntryKey.Contains(keyword) ||
|
|
(entry.Description != null && entry.Description.Contains(keyword)));
|
|
}
|
|
|
|
var items = await query
|
|
.OrderBy(entry => entry.SortOrder)
|
|
.ThenBy(entry => entry.CreatedAt)
|
|
.Take(ResolveLimit(filter.Limit))
|
|
.Select(entry => ToEntryItem(entry))
|
|
.ToArrayAsync(cancellationToken);
|
|
|
|
return new CatalogList<ContentEntryManagementItem>(items);
|
|
}
|
|
|
|
public async Task<ContentManagementResult<ContentEntryManagementItem>> UpsertEntryAsync(
|
|
ContentManagementActor actor,
|
|
UpsertContentEntryCommand command,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var scope = await RequireDataScopeAsync(actor, cancellationToken);
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(command.Name);
|
|
await AssertRegionAsync(actor.TenantId, command.RegionId, cancellationToken);
|
|
|
|
var entryKey = Normalize(command.EntryKey) ??
|
|
Normalize(command.Id?.ToString("N")) ??
|
|
Guid.NewGuid().ToString("N");
|
|
var entry = await ResolveEntityAsync(
|
|
dbContext.ContentEntries,
|
|
actor.TenantId,
|
|
command.Id,
|
|
item => item.EntryKey == entryKey,
|
|
cancellationToken);
|
|
|
|
var isNew = entry is null;
|
|
if (command.Id.HasValue && (entry is null || entry.Id != command.Id.Value))
|
|
throw new ContentManagementException("Content entry was not found.", "entry_not_found");
|
|
|
|
if (entry is not null && !scope.AllowsResource(actor.UserId, entry.CreatedBy, entry.RegionId))
|
|
throw new ContentManagementException("Content entry was not found.", "entry_not_found");
|
|
|
|
if (entry is null && !scope.AllowsResource(actor.UserId, actor.UserId, command.RegionId))
|
|
throw new ContentManagementException("Content entry was not found.", "entry_not_found");
|
|
|
|
entry ??= new ContentEntry
|
|
{
|
|
Id = command.Id ?? Guid.NewGuid(),
|
|
TenantId = actor.TenantId,
|
|
EntryKey = entryKey,
|
|
CreatedBy = actor.UserId
|
|
};
|
|
|
|
entry.RegionId = command.RegionId;
|
|
entry.LegacyId = Normalize(command.LegacyId);
|
|
entry.Name = command.Name.Trim();
|
|
entry.EntryType = Parse(command.EntryType, ContentEntryType.QuestionPractice, "entry_type_invalid");
|
|
entry.Icon = Normalize(command.Icon);
|
|
entry.Route = Normalize(command.Route);
|
|
entry.Description = Normalize(command.Description);
|
|
entry.Visibility = Parse(command.Visibility, ContentVisibility.Public, "visibility_invalid");
|
|
entry.AccessRules = JsonObjectOrDefault(command.AccessRules);
|
|
entry.LayoutConfig = JsonObjectOrDefault(command.LayoutConfig);
|
|
entry.SortOrder = command.Order ?? 0;
|
|
entry.IsActive = command.IsActive ?? true;
|
|
entry.UpdatedBy = actor.UserId;
|
|
|
|
if (isNew) dbContext.ContentEntries.Add(entry);
|
|
|
|
await dbContext.SaveChangesAsync(cancellationToken);
|
|
return new ContentManagementResult<ContentEntryManagementItem>(ToEntryItem(entry));
|
|
}
|
|
} |