diff --git a/PortBlog.API/Controllers/BlogController.cs b/PortBlog.API/Controllers/BlogController.cs index 96b42d0..ed22016 100644 --- a/PortBlog.API/Controllers/BlogController.cs +++ b/PortBlog.API/Controllers/BlogController.cs @@ -1,6 +1,7 @@ using Asp.Versioning; using AutoMapper; using Microsoft.AspNetCore.Mvc; +using PortBlog.API.Entities; using PortBlog.API.Models; using PortBlog.API.Repositories.Contracts; @@ -18,29 +19,35 @@ namespace PortBlog.API.Controllers public BlogController(ILogger logger, IBlogRepository blogRepository, IMapper mapper) { - this._logger = logger; - this._blogRepository = blogRepository; - this._mapper = mapper; + _logger = logger; + _blogRepository = blogRepository; + _mapper = mapper; } [HttpGet("GetPostLikesAndViews")] - public async Task GetPostLikesAndViews(string blogUrl, string postSlug) + public async Task> GetPostLikesAndViews(string blogUrl, string postSlug) { var postMetrics = new PostMetricsDto(); - if(!await this._blogRepository.BlogExistsAsync(blogUrl)) + if(!await _blogRepository.BlogExistsAsync(blogUrl)) { _logger.LogInformation($"Blog with id {blogUrl} wasn't found when fetching post likes and views."); return NotFound(); } - if (!await this._blogRepository.PostExistsAsync(blogUrl, postSlug)) + if (!await _blogRepository.PostExistsAsync(blogUrl, postSlug)) { _logger.LogInformation($"Post with id {postSlug} wasn't found when fetching post likes and views."); return Ok(postMetrics); } - var post = await _blogRepository.GetPostLikesAndViewsAsync(blogUrl, postSlug); + var post = await _blogRepository.GetPostAsync(blogUrl, postSlug); + + post.Views++; + + _blogRepository.UpdatePost(post); + + await _blogRepository.SaveChangesAsync(); postMetrics = _mapper.Map(post); @@ -48,5 +55,72 @@ namespace PortBlog.API.Controllers return Ok(postMetrics); } + + [HttpPost("CreatePost")] + public async Task> CreatePost([FromBody] PostCreationDto post) + { + if (!await _blogRepository.BlogExistsAsync(post.BlogUrl)) + { + _logger.LogInformation($"Blog with id {post.BlogUrl} wasn't found when fetching post likes and views."); + return NotFound(); + } + + var postEntityExists = await _blogRepository.GetPostAsync(post.BlogUrl, post.Slug); + + if (postEntityExists == null) + { + postEntityExists = _mapper.Map(post); + + postEntityExists.Views++; + + _blogRepository.AddPost(postEntityExists); + + await _blogRepository.SaveChangesAsync(); + } + + var postMetrics = _mapper.Map(postEntityExists); + postMetrics.PostExists = true; + return Ok(postMetrics); + } + + [HttpPost("LikePost")] + public async Task> LikePost(string blogUrl, string postSlug) + { + if (!await _blogRepository.PostExistsAsync(blogUrl, postSlug)) + { + _logger.LogInformation($"Post with id {postSlug} wasn't found when fetching post likes and views."); + return NotFound(); + } + + var post = await _blogRepository.GetPostAsync(blogUrl, postSlug); + + post.Likes++; + + _blogRepository.UpdatePost(post); + + await _blogRepository.SaveChangesAsync(); + + return Ok(post.Likes); + } + + [HttpPost("DislikePost")] + public async Task> DislikePost(string blogUrl, string postSlug) + { + if (!await _blogRepository.PostExistsAsync(blogUrl, postSlug)) + { + _logger.LogInformation($"Post with id {postSlug} wasn't found when fetching post likes and views."); + return NotFound(); + } + + var post = await _blogRepository.GetPostAsync(blogUrl, postSlug); + + post.Likes--; + + _blogRepository.UpdatePost(post); + + await _blogRepository.SaveChangesAsync(); + + return Ok(post.Likes); + } } } diff --git a/PortBlog.API/Models/PostCreatedDto.cs b/PortBlog.API/Models/PostCreationDto.cs similarity index 87% rename from PortBlog.API/Models/PostCreatedDto.cs rename to PortBlog.API/Models/PostCreationDto.cs index 7c5c25e..090f3bf 100644 --- a/PortBlog.API/Models/PostCreatedDto.cs +++ b/PortBlog.API/Models/PostCreationDto.cs @@ -1,6 +1,6 @@ namespace PortBlog.API.Models { - public class PostCreatedDto + public class PostCreationDto { public int PostId { get; set; } @@ -25,5 +25,7 @@ public string? CreatedDate { get; set; } public string? ModifiedDate { get; set; } + + public string BlogUrl { get; set;} = string.Empty; } } diff --git a/PortBlog.API/Profiles/BlogProfile.cs b/PortBlog.API/Profiles/BlogProfile.cs index 6f917dd..559aabb 100644 --- a/PortBlog.API/Profiles/BlogProfile.cs +++ b/PortBlog.API/Profiles/BlogProfile.cs @@ -19,6 +19,7 @@ namespace PortBlog.API.Profiles opts => opts.MapFrom(src => src.ModifiedDate != null ? src.ModifiedDate.Value.ToString("MMM dd, yyyy") : string.Empty) ); CreateMap(); + CreateMap(); } } } diff --git a/PortBlog.API/Program.cs b/PortBlog.API/Program.cs index 99b7dbc..5a15ad0 100644 --- a/PortBlog.API/Program.cs +++ b/PortBlog.API/Program.cs @@ -50,7 +50,7 @@ if (!String.IsNullOrEmpty(allowedCorsOrigins.Value)) policy => { policy.WithOrigins(origins); - policy.WithHeaders("XApiKey"); + policy.AllowAnyHeader(); }); }); } diff --git a/PortBlog.API/Repositories/BlogRepository.cs b/PortBlog.API/Repositories/BlogRepository.cs index b5b3ff0..a9e5813 100644 --- a/PortBlog.API/Repositories/BlogRepository.cs +++ b/PortBlog.API/Repositories/BlogRepository.cs @@ -24,7 +24,7 @@ namespace PortBlog.API.Repositories return await _cvBlogContext.Blogs.Where(b => b.BlogUrl == blogUrl).FirstOrDefaultAsync(); } - public async Task GetPostLikesAndViewsAsync(string blogUrl, string postSlug) + public async Task GetPostAsync(string blogUrl, string postSlug) { return await _cvBlogContext.Posts.Where(p => p.Slug == postSlug && p.BlogUrl == blogUrl).FirstOrDefaultAsync(); } @@ -37,7 +37,22 @@ namespace PortBlog.API.Repositories public async Task BlogExistsAsync(string blogUrl) { - return await _cvBlogContext.Posts.AnyAsync(b => b.BlogUrl == blogUrl); + return await _cvBlogContext.Blogs.AnyAsync(b => b.BlogUrl == blogUrl); + } + + public void AddPost(Post post) + { + _cvBlogContext.Posts.Add(post); + } + + public void UpdatePost(Post post) + { + _cvBlogContext.Posts.Update(post); + } + + public async Task SaveChangesAsync() + { + return (await _cvBlogContext.SaveChangesAsync() >= 0); } } } diff --git a/PortBlog.API/Repositories/Contracts/IBlogRepository.cs b/PortBlog.API/Repositories/Contracts/IBlogRepository.cs index cbdd270..8c37010 100644 --- a/PortBlog.API/Repositories/Contracts/IBlogRepository.cs +++ b/PortBlog.API/Repositories/Contracts/IBlogRepository.cs @@ -6,10 +6,16 @@ namespace PortBlog.API.Repositories.Contracts { Task GetBlogAsync(string blogUrl, bool includePosts); - Task GetPostLikesAndViewsAsync(string blogUrl, string postSlug); + Task GetPostAsync(string blogUrl, string postSlug); Task PostExistsAsync(string blogUrl, string postSlug); Task BlogExistsAsync(string blogUrl); + + void AddPost(Post post); + + void UpdatePost(Post post); + + Task SaveChangesAsync(); } }