Document post endpoints

This commit is contained in:
2025-10-06 16:58:13 +03:00
parent 8d012f04f1
commit 0a4bd23d30
7 changed files with 111 additions and 23 deletions

View File

@@ -7,11 +7,7 @@ meta {
post {
url: {{baseUrl}}/api/posts/1/comments
body: json
auth: bearer
}
auth:bearer {
token: {{accessToken}}
auth: inherit
}
body:json {

View File

@@ -7,9 +7,5 @@ meta {
delete {
url: {{baseUrl}}/api/posts/1/comments/1
body: none
auth: bearer
}
auth:bearer {
token: {{accessToken}}
auth: inherit
}

View File

@@ -7,11 +7,7 @@ meta {
patch {
url: {{baseUrl}}/api/posts/1/comments/1
body: json
auth: bearer
}
auth:bearer {
token: {{accessToken}}
auth: inherit
}
body:json {

View File

@@ -0,0 +1,23 @@
meta {
name: Login as admin
type: http
seq: 5
}
post {
url: {{baseUrl}}/api/auth/login
body: json
auth: none
}
body:json {
{
"email": "admin@localhost",
"password": "ChangeMe123#"
}
}
vars:post-response {
accessToken: res.body.accessToken
refreshToken: res.body.refreshToken
}

View File

@@ -7,7 +7,7 @@ meta {
post {
url: {{baseUrl}}/api/auth/login
body: json
auth: inherit
auth: none
}
body:json {

View File

@@ -7,7 +7,7 @@ meta {
post {
url: {{baseUrl}}/api/auth/register
body: json
auth: inherit
auth: none
}
body:json {

View File

@@ -109,11 +109,20 @@ public class PostController(
return tags;
}
/// <summary>
/// Begins the creation process of a new post.
/// </summary>
/// <param name="dto">Post metadata</param>
/// <response code="201">Returns post metadata</response>
/// <response code="400">If request is malformed</response>
/// <response code="401">If authentication is missing</response>
/// <response code="403">If authorization is missing</response>
[HttpPost]
[Authorize]
[Authorize(Roles = UserRoles.Regular)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<ActionResult<PostDto>> Create(CreatePostDto dto)
{
var userId = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value;
@@ -143,7 +152,27 @@ public class PostController(
PostDto.FromPost(created.Post, fileUrl));
}
/// <summary>
/// Uploads a file chunk of the associated post.
/// </summary>
/// <param name="postId">Associated post</param>
/// <param name="fileId">ID of file being uploaded</param>
/// <response code="202">If file chunk was accepted</response>
/// <response code="204">If file was successfully uploaded</response>
/// <response code="400">If request is malformed</response>
/// <response code="401">If authentication is missing</response>
/// <response code="403">If authorization is missing</response>
/// <response code="404">If post or file is not found</response>
/// <response code="415">If finished upload mime does not match provided</response>
[HttpPatch("{postId:int}/files/{fileId:int}")]
[Authorize(Roles = UserRoles.Regular)]
[ProducesResponseType(StatusCodes.Status202Accepted)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status415UnsupportedMediaType)]
public async Task<IActionResult> PatchFileContent(int postId, int fileId)
{
var post = await postService.GetById(postId, includeUnfinished: true);
@@ -152,11 +181,14 @@ public class PostController(
var fileRecord = await fileService.GetFileById(fileId);
if (fileRecord == null) return NotFound();
// If not the resource owner
var userId = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value;
if (userId != post.Author.Id) Forbid();
if (fileRecord.FinishedDate != null)
return Problem(statusCode: StatusCodes.Status400BadRequest,
detail: "File was already uploaded.");
// Parse the Content-Range Header
// Example: Content-Range: bytes 0-1048575/5242880
var rangeHeader = Request.Headers.ContentRange.FirstOrDefault();
@@ -214,7 +246,18 @@ public class PostController(
return NoContent();
}
/// <summary>
/// Get the specified file content of the associated post.
/// </summary>
/// <param name="postId">Associated post ID</param>
/// <param name="fileId">File ID</param>
/// <response code="200">The file content</response>
/// <response code="400">If request is malformed</response>
/// <response code="404">If post or file is not found</response>
[HttpGet("{postId:int}/files/{fileId:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetFileContent(int postId, int fileId)
{
var post = await postService.GetById(postId, includeUnfinished: true);
@@ -242,6 +285,13 @@ public class PostController(
return File(stream, fileRecord.ContentType, fileRecord.OriginalFileName);
}
/// <summary>
/// Get the specified post.
/// </summary>
/// <param name="id">Post ID</param>
/// <response code="200">The post content</response>
/// <response code="400">If request is malformed</response>
/// <response code="404">If post is not found</response>
[HttpGet("{id:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
@@ -256,6 +306,13 @@ public class PostController(
return Ok(PostDto.FromPost(entry, fileUrl));
}
/// <summary>
/// Get a paginated list of posts.
/// </summary>
/// <param name="query">Query to filter posts by tags. Use +tag-name to require a tag, -tag-name to exclude a tag.</param>
/// <param name="pageNumber">The page number.</param>
/// <response code="200">The paginated list</response>
/// <response code="400">If request is malformed</response>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
@@ -272,11 +329,21 @@ public class PostController(
return Ok(new PagedList<PostDto>(newItems, list.CurrentPage, list.PageSize, list.TotalCount));
}
[Authorize]
/// <summary>
/// Delete specified post.
/// </summary>
/// <param name="id">Post ID</param>
/// <response code="204">If deleted successfully</response>
/// <response code="400">If request is malformed</response>
/// <response code="401">If authentication is missing</response>
/// <response code="403">If authorization is missing</response>
/// <response code="404">If post is not found</response>
[Authorize(Roles = UserRoles.Regular)]
[HttpDelete("{id:int}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> Delete(int id)
{
@@ -302,7 +369,17 @@ public class PostController(
return NoContent();
}
[Authorize]
/// <summary>
/// Update specified post.
/// </summary>
/// <param name="id">Post ID</param>
/// <param name="dto">Post edit data</param>
/// <response code="200">New post data</response>
/// <response code="400">If request is malformed</response>
/// <response code="401">If authentication is missing</response>
/// <response code="403">If authorization is missing</response>
/// <response code="404">If post is not found</response>
[Authorize(Roles = UserRoles.Regular)]
[HttpPatch("{id:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]