diff --git a/Bruno/Endpoints/Posts/Comments/Create a post comment.bru b/Bruno/Endpoints/Posts/Comments/Create a post comment.bru
index f3a515b..32ed171 100644
--- a/Bruno/Endpoints/Posts/Comments/Create a post comment.bru
+++ b/Bruno/Endpoints/Posts/Comments/Create a post comment.bru
@@ -7,11 +7,7 @@ meta {
post {
url: {{baseUrl}}/api/posts/1/comments
body: json
- auth: bearer
-}
-
-auth:bearer {
- token: {{accessToken}}
+ auth: inherit
}
body:json {
diff --git a/Bruno/Endpoints/Posts/Comments/Delete post comment.bru b/Bruno/Endpoints/Posts/Comments/Delete post comment.bru
index 8e7f11d..1e1ac4b 100644
--- a/Bruno/Endpoints/Posts/Comments/Delete post comment.bru
+++ b/Bruno/Endpoints/Posts/Comments/Delete post comment.bru
@@ -7,9 +7,5 @@ meta {
delete {
url: {{baseUrl}}/api/posts/1/comments/1
body: none
- auth: bearer
-}
-
-auth:bearer {
- token: {{accessToken}}
+ auth: inherit
}
diff --git a/Bruno/Endpoints/Posts/Comments/Update specific post comment.bru b/Bruno/Endpoints/Posts/Comments/Update specific post comment.bru
index 44f4d7b..d5609f2 100644
--- a/Bruno/Endpoints/Posts/Comments/Update specific post comment.bru
+++ b/Bruno/Endpoints/Posts/Comments/Update specific post comment.bru
@@ -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 {
diff --git a/Bruno/Seed/Create accounts/Login as admin.bru b/Bruno/Seed/Create accounts/Login as admin.bru
new file mode 100644
index 0000000..ae926ca
--- /dev/null
+++ b/Bruno/Seed/Create accounts/Login as admin.bru
@@ -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
+}
diff --git a/Bruno/Seed/Create accounts/Login as normal.bru b/Bruno/Seed/Create accounts/Login as normal.bru
index bd20487..3ba4854 100644
--- a/Bruno/Seed/Create accounts/Login as normal.bru
+++ b/Bruno/Seed/Create accounts/Login as normal.bru
@@ -7,7 +7,7 @@ meta {
post {
url: {{baseUrl}}/api/auth/login
body: json
- auth: inherit
+ auth: none
}
body:json {
diff --git a/Bruno/Seed/Create accounts/Register normal user.bru b/Bruno/Seed/Create accounts/Register normal user.bru
index 60e1870..b9c3061 100644
--- a/Bruno/Seed/Create accounts/Register normal user.bru
+++ b/Bruno/Seed/Create accounts/Register normal user.bru
@@ -7,7 +7,7 @@ meta {
post {
url: {{baseUrl}}/api/auth/register
body: json
- auth: inherit
+ auth: none
}
body:json {
diff --git a/T120B165-ImgBoard/Controllers/PostController.cs b/T120B165-ImgBoard/Controllers/PostController.cs
index 28c4ff8..6e26089 100644
--- a/T120B165-ImgBoard/Controllers/PostController.cs
+++ b/T120B165-ImgBoard/Controllers/PostController.cs
@@ -109,11 +109,20 @@ public class PostController(
return tags;
}
+ ///
+ /// Begins the creation process of a new post.
+ ///
+ /// Post metadata
+ /// Returns post metadata
+ /// If request is malformed
+ /// If authentication is missing
+ /// If authorization is missing
[HttpPost]
- [Authorize]
+ [Authorize(Roles = UserRoles.Regular)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
- [ProducesResponseType(StatusCodes.Status409Conflict)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task> 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));
}
+ ///
+ /// Uploads a file chunk of the associated post.
+ ///
+ /// Associated post
+ /// ID of file being uploaded
+ /// If file chunk was accepted
+ /// If file was successfully uploaded
+ /// If request is malformed
+ /// If authentication is missing
+ /// If authorization is missing
+ /// If post or file is not found
+ /// If finished upload mime does not match provided
[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 PatchFileContent(int postId, int fileId)
{
var post = await postService.GetById(postId, includeUnfinished: true);
@@ -151,11 +180,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
@@ -214,7 +246,18 @@ public class PostController(
return NoContent();
}
+ ///
+ /// Get the specified file content of the associated post.
+ ///
+ /// Associated post ID
+ /// File ID
+ /// The file content
+ /// If request is malformed
+ /// If post or file is not found
[HttpGet("{postId:int}/files/{fileId:int}")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task 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);
}
+ ///
+ /// Get the specified post.
+ ///
+ /// Post ID
+ /// The post content
+ /// If request is malformed
+ /// If post is not found
[HttpGet("{id:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
@@ -256,6 +306,13 @@ public class PostController(
return Ok(PostDto.FromPost(entry, fileUrl));
}
+ ///
+ /// Get a paginated list of posts.
+ ///
+ /// Query to filter posts by tags. Use +tag-name to require a tag, -tag-name to exclude a tag.
+ /// The page number.
+ /// The paginated list
+ /// If request is malformed
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
@@ -272,11 +329,21 @@ public class PostController(
return Ok(new PagedList(newItems, list.CurrentPage, list.PageSize, list.TotalCount));
}
-
- [Authorize]
+ ///
+ /// Delete specified post.
+ ///
+ /// Post ID
+ /// If deleted successfully
+ /// If request is malformed
+ /// If authentication is missing
+ /// If authorization is missing
+ /// If post is not found
+ [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 Delete(int id)
{
@@ -302,7 +369,17 @@ public class PostController(
return NoContent();
}
- [Authorize]
+ ///
+ /// Update specified post.
+ ///
+ /// Post ID
+ /// Post edit data
+ /// New post data
+ /// If request is malformed
+ /// If authentication is missing
+ /// If authorization is missing
+ /// If post is not found
+ [Authorize(Roles = UserRoles.Regular)]
[HttpPatch("{id:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]