using Microsoft.Extensions.Options; using Netina.Domain.Entities.Blogs; using System.Web; using Netina.Repository.Abstracts; namespace Netina.Api.Controllers; public class BlogController : ICarterModule { public virtual void AddRoutes(IEndpointRouteBuilder app) { var group = app.NewVersionedApi("Blog") .MapGroup($"api/blog"); group.MapGet("", GetAllAsync) .WithDisplayName("Get Blogs") .HasApiVersion(1.0); group.MapGet("{id}", GetAsync) .WithDisplayName("Get Blog") .HasApiVersion(1.0); group.MapPost("", Post) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser() .RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs)) .WithDisplayName("Create Blog") .HasApiVersion(1.0); group.MapPut("", Put) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser() .RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs)) .WithDisplayName("Update Blog") .HasApiVersion(1.0); group.MapGet("{blogId}/comment", GetBlogCommentsAsync) .WithDisplayName("Get Blog Comments") .HasApiVersion(1.0); group.MapDelete("{id}", Delete) .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser() .RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageBlogs)) .WithDisplayName("Delete Blog") .HasApiVersion(1.0); group.MapGet("/newlink", GetBlogNewLinkAsync) .WithDisplayName("Get Blog NewLink") .HasApiVersion(1.0); } private async Task GetBlogCommentsAsync([FromQuery] int page, [FromQuery] int count, [FromRoute] Guid blogId, IMediator mediator, CancellationToken cancellationToken) => TypedResults.Ok(await mediator.Send(new GetCommentsQuery(page, count, null, blogId), cancellationToken)); private async Task GetBlogNewLinkAsync([FromQuery]string slug,IRepositoryWrapper repositoryWrapper,IOptionsSnapshot snapshot,CancellationToken cancellationToken) { var htmlSlug = HttpUtility.UrlEncode(slug); var blog = await repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(b => b.Slug== htmlSlug, cancellationToken); if (blog == null) throw new BaseApiException(ApiResultStatusCode.NotFound, "Blog not found"); var website = snapshot.Value.WebSiteUrl; var response = $"{website}/blogs/{blog.Id}/{blog.Slug}"; return TypedResults.Content(response); } // GET:Get All Entity public async Task GetAllAsync([FromQuery] int page, [FromQuery]int? count, [FromQuery] Guid? blogCategoryId, [FromQuery]string? blogName, IMediator mediator, CancellationToken cancellationToken) => TypedResults.Ok(await mediator.Send(new GetBlogsQuery(page,Count: count, CategoryId: blogCategoryId,BlogName: blogName), cancellationToken)); // GET:Get An Entity By Id public async Task GetAsync(Guid id, IRepositoryWrapper repositoryWrapper, CancellationToken cancellationToken) { var dto = await repositoryWrapper.SetRepository().TableNoTracking .Where(b => b.Id == id) .Select(BlogMapper.ProjectToLDto) .FirstOrDefaultAsync(cancellationToken); return TypedResults.Ok(dto); } // POST:Create Entity public async Task Post([FromBody] BlogLDto dto, IRepositoryWrapper repositoryWrapper,ICurrentUserService currentUserService, CancellationToken cancellationToken) { if (currentUserService.UserId == null) throw new BaseApiException(ApiResultStatusCode.UnAuthorized, "User id is wrong"); if (!Guid.TryParse(currentUserService.UserId, out Guid userId)) throw new BaseApiException(ApiResultStatusCode.UnAuthorized, "User id is wrong"); var ent = Blog.Create(dto.Title, dto.Content, dto.Tags, dto.ReadingTime, dto.Summery, dto.IsSuggested,dto.CategoryId, userId); foreach (var file in dto.Files) { ent.AddFile(file.Name, file.FileLocation, file.FileName, file.IsHeader, file.IsPrimary, file.FileType); } foreach (var item in dto.MetaTags) ent.AddMetaTag(item.Type, item.Value); repositoryWrapper.SetRepository().Add(ent); await repositoryWrapper.SaveChangesAsync(cancellationToken); return TypedResults.Ok(ent.AdaptToSDto()); } // PUT:Update Entity public async Task Put([FromBody] BlogLDto dto, IRepositoryWrapper repositoryWrapper, ICurrentUserService currentUserService, CancellationToken cancellationToken) { var ent = await repositoryWrapper.SetRepository().TableNoTracking .FirstOrDefaultAsync(b => b.Id == dto.Id, cancellationToken); if (ent == null) throw new AppException("Blog not found"); if (currentUserService.UserId == null) throw new BaseApiException(ApiResultStatusCode.UnAuthorized, "User id is wrong"); if (!Guid.TryParse(currentUserService.UserId, out Guid userId)) throw new BaseApiException(ApiResultStatusCode.UnAuthorized, "User id is wrong"); var newEnt = Blog.Create(dto.Title, dto.Content, dto.Tags, dto.ReadingTime, dto.Summery, dto.IsSuggested, dto.CategoryId, userId); newEnt.Id = ent.Id; newEnt.CreatedAt = ent.CreatedAt; newEnt.CreatedBy = ent.CreatedBy; var dbFiles = await repositoryWrapper.SetRepository().TableNoTracking .Where(s => s.BlogId == newEnt.Id).ToListAsync(cancellationToken); foreach (var dbFile in dbFiles) { if (dto.Files.FirstOrDefault(s => s.Id == dbFile.Id) == null) { repositoryWrapper.SetRepository().Delete(dbFile); await repositoryWrapper.SaveChangesAsync(cancellationToken); } } foreach (var file in dto.Files.Where(f => f.Id == default)) newEnt.AddFile(file.Name, file.FileLocation, file.FileName, file.IsHeader, file.IsPrimary, file.FileType); //Check MetaTags var dbMetaTags = await repositoryWrapper.SetRepository() .TableNoTracking .Where(f => f.BlogId == ent.Id) .ToListAsync(cancellationToken); foreach (var feature in dbMetaTags.Where(feature => dto.MetaTags.Any(f => f.Type == feature.Type) == false)) { repositoryWrapper.SetRepository() .Delete(feature); await repositoryWrapper.SaveChangesAsync(cancellationToken); } foreach (var item in dto.MetaTags.Where(f => dbMetaTags.Any(dbf => dbf.Type == f.Type) == false)) newEnt.AddMetaTag(item.Type, item.Value); repositoryWrapper.SetRepository().Update(newEnt); await repositoryWrapper.SaveChangesAsync(cancellationToken); return TypedResults.Ok(); } // DELETE:Delete Entity public async Task Delete(Guid id, IRepositoryWrapper repositoryWrapper, CancellationToken cancellationToken) { var ent = await repositoryWrapper.SetRepository().TableNoTracking .FirstOrDefaultAsync(b => b.Id == id, cancellationToken); if (ent == null) throw new AppException("Blog not found"); repositoryWrapper.SetRepository().Delete(ent); await repositoryWrapper.SaveChangesAsync(cancellationToken); return TypedResults.Ok(); } }