|
|
|
@@ -109,11 +109,20 @@ public class PostController(
|
|
|
|
return tags;
|
|
|
|
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]
|
|
|
|
[HttpPost]
|
|
|
|
[Authorize]
|
|
|
|
[Authorize(Roles = UserRoles.Regular)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status201Created)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status201Created)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
|
|
|
|
|
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
|
|
|
public async Task<ActionResult<PostDto>> Create(CreatePostDto dto)
|
|
|
|
public async Task<ActionResult<PostDto>> Create(CreatePostDto dto)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var userId = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value;
|
|
|
|
var userId = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value;
|
|
|
|
@@ -143,7 +152,27 @@ public class PostController(
|
|
|
|
PostDto.FromPost(created.Post, fileUrl));
|
|
|
|
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}")]
|
|
|
|
[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)
|
|
|
|
public async Task<IActionResult> PatchFileContent(int postId, int fileId)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var post = await postService.GetById(postId, includeUnfinished: true);
|
|
|
|
var post = await postService.GetById(postId, includeUnfinished: true);
|
|
|
|
@@ -151,11 +180,14 @@ public class PostController(
|
|
|
|
|
|
|
|
|
|
|
|
var fileRecord = await fileService.GetFileById(fileId);
|
|
|
|
var fileRecord = await fileService.GetFileById(fileId);
|
|
|
|
if (fileRecord == null) return NotFound();
|
|
|
|
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)
|
|
|
|
if (fileRecord.FinishedDate != null)
|
|
|
|
return Problem(statusCode: StatusCodes.Status400BadRequest,
|
|
|
|
return Problem(statusCode: StatusCodes.Status400BadRequest,
|
|
|
|
detail: "File was already uploaded.");
|
|
|
|
detail: "File was already uploaded.");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Parse the Content-Range Header
|
|
|
|
// Parse the Content-Range Header
|
|
|
|
// Example: Content-Range: bytes 0-1048575/5242880
|
|
|
|
// Example: Content-Range: bytes 0-1048575/5242880
|
|
|
|
@@ -214,7 +246,18 @@ public class PostController(
|
|
|
|
return NoContent();
|
|
|
|
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}")]
|
|
|
|
[HttpGet("{postId:int}/files/{fileId:int}")]
|
|
|
|
|
|
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
|
|
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
|
|
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
|
|
public async Task<IActionResult> GetFileContent(int postId, int fileId)
|
|
|
|
public async Task<IActionResult> GetFileContent(int postId, int fileId)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var post = await postService.GetById(postId, includeUnfinished: true);
|
|
|
|
var post = await postService.GetById(postId, includeUnfinished: true);
|
|
|
|
@@ -242,6 +285,13 @@ public class PostController(
|
|
|
|
return File(stream, fileRecord.ContentType, fileRecord.OriginalFileName);
|
|
|
|
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}")]
|
|
|
|
[HttpGet("{id:int}")]
|
|
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
@@ -256,6 +306,13 @@ public class PostController(
|
|
|
|
return Ok(PostDto.FromPost(entry, fileUrl));
|
|
|
|
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]
|
|
|
|
[HttpGet]
|
|
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
@@ -272,11 +329,21 @@ public class PostController(
|
|
|
|
return Ok(new PagedList<PostDto>(newItems, list.CurrentPage, list.PageSize, list.TotalCount));
|
|
|
|
return Ok(new PagedList<PostDto>(newItems, list.CurrentPage, list.PageSize, list.TotalCount));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
[Authorize]
|
|
|
|
/// 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}")]
|
|
|
|
[HttpDelete("{id:int}")]
|
|
|
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
|
|
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
|
|
|
|
|
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
|
|
public async Task<ActionResult> Delete(int id)
|
|
|
|
public async Task<ActionResult> Delete(int id)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@@ -302,7 +369,17 @@ public class PostController(
|
|
|
|
return NoContent();
|
|
|
|
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}")]
|
|
|
|
[HttpPatch("{id:int}")]
|
|
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
|
|
|