Merge pull request #2022 from nextcloud/bugfix/1831/comments-api

This commit is contained in:
Julius Härtl
2020-06-15 15:22:03 +02:00
committed by GitHub
4 changed files with 85 additions and 13 deletions

View File

@@ -985,8 +985,8 @@ A list of comments will be provided under the `ocs.data` key. If no or no more c
},
"data": [
{
"id": "175",
"objectId": "12",
"id": 175,
"objectId": 12,
"message": "This is a comment with a mention to @alice",
"actorId": "admin",
"actorType": "users",
@@ -1005,6 +1005,45 @@ A list of comments will be provided under the `ocs.data` key. If no or no more c
}
```
In case a comment is marked as a reply to another comment object, the parent comment will be added as `replyTo` entry to the response. Only the next parent node is added, nested replies are not exposed directly.
```json
[
{
"id": 175,
"objectId": 12,
"message": "This is a comment with a mention to @alice",
"actorId": "admin",
"actorType": "users",
"actorDisplayName": "Administrator",
"creationDateTime": "2020-03-10T10:23:07+00:00",
"mentions": [
{
"mentionId": "alice",
"mentionType": "user",
"mentionDisplayName": "alice"
}
],
"replyTo": {
"id": 175,
"objectId": 12,
"message": "This is a comment with a mention to @alice",
"actorId": "admin",
"actorType": "users",
"actorDisplayName": "Administrator",
"creationDateTime": "2020-03-10T10:23:07+00:00",
"mentions": [
{
"mentionId": "alice",
"mentionType": "user",
"mentionDisplayName": "alice"
}
]
}
}
]
```
### POST /cards/{cardId}/comments - Create a new comment
@@ -1014,7 +1053,7 @@ A list of comments will be provided under the `ocs.data` key. If no or no more c
| --------- | ------- | --------------------------------------- |
| cardId | Integer | The id of the card |
| message | String | The message of the comment, maximum length is limited to 1000 characters |
| parentId | Integer | The start offset used for pagination, defaults to null |
| parentId | Integer | _(optional)_ The start offset used for pagination, defaults to null |
Mentions will be parsed by the server. The server will return a list of mentions in the response to this request as shown below.
@@ -1070,7 +1109,7 @@ A not found response might be returned if:
- The parent comment could not be found
### PUT /cards/{cardId}/comments/{commentId} - Update a new comment
### PUT /cards/{cardId}/comments/{commentId} - Update a comment
#### Request parameters

View File

@@ -55,7 +55,7 @@ class CommentsApiController extends OCSController {
* @NoAdminRequired
* @throws StatusException
*/
public function create(string $cardId, string $message, string $parentId = '0'): DataResponse {
public function create(int $cardId, string $message, int $parentId = 0): DataResponse {
return $this->commentService->create($cardId, $message, $parentId);
}
@@ -63,7 +63,7 @@ class CommentsApiController extends OCSController {
* @NoAdminRequired
* @throws StatusException
*/
public function update(string $cardId, string $commentId, string $message): DataResponse {
public function update(int $cardId, int $commentId, string $message): DataResponse {
return $this->commentService->update($cardId, $commentId, $message);
}
@@ -71,7 +71,7 @@ class CommentsApiController extends OCSController {
* @NoAdminRequired
* @throws StatusException
*/
public function delete(string $cardId, string $commentId): DataResponse {
public function delete(int $cardId, int $commentId): DataResponse {
return $this->commentService->delete($cardId, $commentId);
}
}

View File

@@ -88,20 +88,33 @@ class CommentService {
* @param string $replyTo
* @return DataResponse
* @throws BadRequestException
* @throws NotFoundException
* @throws NotFoundException|NoPermissionException
*/
public function create(string $cardId, string $message, string $replyTo = '0'): DataResponse {
if (!is_numeric($cardId)) {
throw new BadRequestException('A valid card id must be provided');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
// Check if parent is a comment on the same card
if ($replyTo !== '0') {
try {
$comment = $this->commentsManager->get($replyTo);
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) {
throw new CommentNotFoundException();
}
} catch (CommentNotFoundException $e) {
throw new BadRequestException('Invalid parent id: The parent comment was not found or belongs to a different card');
}
}
try {
$comment = $this->commentsManager->create('users', $this->userId, Application::COMMENT_ENTITY_TYPE, $cardId);
$comment->setMessage($message);
$comment->setVerb('comment');
$comment->setParentId($replyTo);
$this->commentsManager->save($comment);
return new DataResponse($this->formatComment($comment));
return new DataResponse($this->formatComment($comment, true));
} catch (\InvalidArgumentException $e) {
throw new BadRequestException('Invalid input values');
} catch (MessageTooLongException $e) {
@@ -122,12 +135,19 @@ class CommentService {
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
try {
$comment = $this->commentsManager->get($commentId);
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) {
throw new CommentNotFoundException();
}
} catch (CommentNotFoundException $e) {
throw new NotFoundException('No comment found.');
}
if ($comment->getActorType() !== 'users' || $comment->getActorId() !== $this->userId) {
throw new NoPermissionException('Only authors are allowed to edit their comment.');
}
if ($comment->getParentId() !== '0') {
$this->permissionService->checkPermission($this->cardMapper, $comment->getParentId(), Acl::PERMISSION_READ);
}
$comment->setMessage($message);
$this->commentsManager->save($comment);
return new DataResponse($this->formatComment($comment));
@@ -141,8 +161,12 @@ class CommentService {
throw new BadRequestException('A valid comment id must be provided');
}
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
try {
$comment = $this->commentsManager->get($commentId);
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) {
throw new CommentNotFoundException();
}
} catch (CommentNotFoundException $e) {
throw new NotFoundException('No comment found.');
}
@@ -153,13 +177,13 @@ class CommentService {
return new DataResponse([]);
}
private function formatComment(IComment $comment): array {
private function formatComment(IComment $comment, $addReplyTo = false): array {
$user = $this->userManager->get($comment->getActorId());
$actorDisplayName = $user !== null ? $user->getDisplayName() : $comment->getActorId();
return [
'id' => $comment->getId(),
'objectId' => $comment->getObjectId(),
$formattedComment = [
'id' => (int)$comment->getId(),
'objectId' => (int)$comment->getObjectId(),
'message' => $comment->getMessage(),
'actorId' => $comment->getActorId(),
'actorType' => $comment->getActorType(),
@@ -181,5 +205,13 @@ class CommentService {
];
}, $comment->getMentions()),
];
try {
if ($addReplyTo && $comment->getParentId() !== '0' && $replyTo = $this->commentsManager->get($comment->getParentId())) {
$formattedComment['replyTo'] = $this->formatComment($replyTo);
}
} catch (CommentNotFoundException $e) {
}
return $formattedComment;
}
}

View File

@@ -32,6 +32,7 @@ export class CommentApi {
async loadComments({ cardId, limit, offset }) {
const api = await axios.get(generateOcsUrl(`apps/deck/api/v1.0/cards`, 2) + `${cardId}/comments`, {
params: { limit, offset },
headers: { 'OCS-APIRequest': 'true' },
})
return api.data.ocs.data