diff --git a/Application/CommentService.cs b/Application/CommentService.cs index 87130e1..279be44 100644 --- a/Application/CommentService.cs +++ b/Application/CommentService.cs @@ -17,27 +17,41 @@ namespace Application _data = data; } - public void PublishComment(PublishCommentCommand cmd) + public Guid PublishComment(PublishCommentCommand cmd) { var link = _linkRepository.GetById(cmd.LinkId); var comment = link.AddComment(cmd.Content); _commentRepository.Add(comment); + + return comment.Id; } public CommentDTO[] GetAllLinkComments(Guid linkId) { - return _data.Comments + return CommentDTOs(linkId).ToArray(); + } + + public CommentDTO GetCommentById(Guid id) + { + return CommentDTOs().Single(comment => comment.Id == id); + } + + private IQueryable CommentDTOs(Guid? linkId = null) + { + var comments = linkId.HasValue ? + _data.Comments.Where(comment => comment.LinkId == linkId) + : _data.Comments; + + return comments .OrderByDescending(comment => comment.CreatedAt) - .Where(comment => comment.LinkId == linkId) .Select(comment => new CommentDTO { Id = comment.Id, Content = comment.Content, UpvotesCount = 0, DownvotesCount = 0, - }) - .ToArray(); + }); } } } \ No newline at end of file diff --git a/Apps/Api/Api.csproj b/Apps/Api/Api.csproj index 5835475..413ada0 100644 --- a/Apps/Api/Api.csproj +++ b/Apps/Api/Api.csproj @@ -6,6 +6,10 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + @@ -21,4 +25,9 @@ C:\Users\Julien\Documents\Sources\cesi\hn-20-2\Apps\Api\Api.xml --> + + + + + diff --git a/Apps/Api/Controllers/CommentsController.cs b/Apps/Api/Controllers/CommentsController.cs new file mode 100644 index 0000000..b9c255b --- /dev/null +++ b/Apps/Api/Controllers/CommentsController.cs @@ -0,0 +1,48 @@ +using System; +using Application; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace Api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class CommentsController : ControllerBase + { + private readonly CommentService _commentService; + + public CommentsController(CommentService commentService) + { + _commentService = commentService; + } + + /// + /// Affiche un commentaire. + /// + /// + /// + [HttpGet("{id:guid}")] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status200OK)] + public CommentDTO Show(Guid id) + { + return _commentService.GetCommentById(id); + } + + /// + /// Publie un nouveau commentaire sur la plateforme. + /// + /// + /// + [HttpPost] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status201Created)] + public IActionResult Create(PublishCommentCommand cmd) + { + var commentId = _commentService.PublishComment(cmd); + + return CreatedAtAction(nameof(Show), new { id = commentId }, null); + } + } +} \ No newline at end of file diff --git a/Apps/Api/Controllers/LinksController.cs b/Apps/Api/Controllers/LinksController.cs index 199c429..0485470 100644 --- a/Apps/Api/Controllers/LinksController.cs +++ b/Apps/Api/Controllers/LinksController.cs @@ -10,10 +10,12 @@ namespace Api.Controllers public class LinksController : ControllerBase { private readonly LinkService _linkService; + private readonly CommentService _commentService; - public LinksController(LinkService linkService) + public LinksController(LinkService linkService, CommentService commentService) { _linkService = linkService; + _commentService = commentService; } /// @@ -39,6 +41,17 @@ namespace Api.Controllers return _linkService.GetLinkById(id); } + /// + /// Récupère tous les commentaires associés à un lien. + /// + /// + /// + [HttpGet("{id:guid}/comments")] + public CommentDTO[] Comments(Guid id) + { + return _commentService.GetAllLinkComments(id); + } + /// /// Permet de publier un nouveau lien sur la plateforme. /// diff --git a/Apps/Api/api.http b/Apps/Api/api.http index 3400d67..91ec5b6 100644 --- a/Apps/Api/api.http +++ b/Apps/Api/api.http @@ -9,4 +9,18 @@ Content-Type: application/json { "url": "http://google.com" +} + +### + +GET {{url}}/api/links/0860619e-6a13-45fe-86a8-6aa64e263f38/comments + +### + +POST {{url}}/api/comments +Content-Type: application/json + +{ + "linkId": "55be28a5-fdfb-48f7-8442-5f900048c292", + "content": "a new comment!" } \ No newline at end of file diff --git a/Apps/Api/swagger.json b/Apps/Api/swagger.json new file mode 100644 index 0000000..fd26ec7 --- /dev/null +++ b/Apps/Api/swagger.json @@ -0,0 +1,359 @@ +{ + "x-generator": "NSwag v13.10.9.0 (NJsonSchema v10.4.1.0 (Newtonsoft.Json v12.0.0.0))", + "openapi": "3.0.0", + "info": { + "title": "Hacker News Clone API", + "version": "1.0.0" + }, + "paths": { + "/api/Comments/{id}": { + "get": { + "tags": [ + "Comments" + ], + "summary": "Affiche un commentaire.", + "operationId": "Comments_Show", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "guid" + }, + "x-position": 1 + } + ], + "responses": { + "404": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CommentDTO" + } + } + } + } + } + } + }, + "/api/Comments": { + "post": { + "tags": [ + "Comments" + ], + "summary": "Publie un nouveau commentaire sur la plateforme.", + "operationId": "Comments_Create", + "requestBody": { + "x-name": "cmd", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublishCommentCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "404": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "201": { + "description": "" + } + } + } + }, + "/api/links": { + "get": { + "tags": [ + "Links" + ], + "summary": "Récupère la liste liste des derniers liens publiés.", + "operationId": "Links_Index", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LinkDTO" + } + } + } + } + } + } + }, + "post": { + "tags": [ + "Links" + ], + "summary": "Permet de publier un nouveau lien sur la plateforme.", + "operationId": "Links_Create", + "requestBody": { + "x-name": "cmd", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublishLinkCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "201": { + "description": "" + } + } + } + }, + "/api/links/{id}": { + "get": { + "tags": [ + "Links" + ], + "summary": "Récupère les détails d'un lien.", + "operationId": "Links_Show", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "guid" + }, + "x-position": 1 + } + ], + "responses": { + "404": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkDTO" + } + } + } + } + } + } + }, + "/api/links/{id}/comments": { + "get": { + "tags": [ + "Links" + ], + "summary": "Récupère tous les commentaires associés à un lien.", + "operationId": "Links_Comments", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "guid" + }, + "x-position": 1 + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommentDTO" + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "ProblemDetails": { + "type": "object", + "additionalProperties": { + "nullable": true + }, + "properties": { + "type": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "status": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "instance": { + "type": "string", + "nullable": true + }, + "extensions": { + "type": "object", + "nullable": true, + "additionalProperties": {} + } + } + }, + "CommentDTO": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "guid" + }, + "content": { + "type": "string", + "nullable": true + }, + "upvotesCount": { + "type": "integer", + "format": "int32" + }, + "downvotesCount": { + "type": "integer", + "format": "int32" + } + } + }, + "PublishCommentCommand": { + "type": "object", + "additionalProperties": false, + "required": [ + "linkId", + "content" + ], + "properties": { + "linkId": { + "type": "string", + "format": "guid", + "minLength": 1 + }, + "content": { + "type": "string", + "minLength": 1 + } + } + }, + "LinkDTO": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "guid" + }, + "url": { + "type": "string", + "nullable": true + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "upvotesCount": { + "type": "integer", + "format": "int32" + }, + "downvotesCount": { + "type": "integer", + "format": "int32" + }, + "commentsCount": { + "type": "integer", + "format": "int32" + } + } + }, + "PublishLinkCommand": { + "type": "object", + "additionalProperties": false, + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string", + "format": "uri", + "minLength": 1 + } + } + } + } + } +} \ No newline at end of file