Merge pull request #2022 from nextcloud/bugfix/1831/comments-api
This commit is contained in:
47
docs/API.md
47
docs/API.md
@@ -985,8 +985,8 @@ A list of comments will be provided under the `ocs.data` key. If no or no more c
|
|||||||
},
|
},
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
"id": "175",
|
"id": 175,
|
||||||
"objectId": "12",
|
"objectId": 12,
|
||||||
"message": "This is a comment with a mention to @alice",
|
"message": "This is a comment with a mention to @alice",
|
||||||
"actorId": "admin",
|
"actorId": "admin",
|
||||||
"actorType": "users",
|
"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
|
### 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 |
|
| cardId | Integer | The id of the card |
|
||||||
| message | String | The message of the comment, maximum length is limited to 1000 characters |
|
| 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.
|
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
|
- 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
|
#### Request parameters
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class CommentsApiController extends OCSController {
|
|||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @throws StatusException
|
* @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);
|
return $this->commentService->create($cardId, $message, $parentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ class CommentsApiController extends OCSController {
|
|||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @throws StatusException
|
* @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);
|
return $this->commentService->update($cardId, $commentId, $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ class CommentsApiController extends OCSController {
|
|||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @throws StatusException
|
* @throws StatusException
|
||||||
*/
|
*/
|
||||||
public function delete(string $cardId, string $commentId): DataResponse {
|
public function delete(int $cardId, int $commentId): DataResponse {
|
||||||
return $this->commentService->delete($cardId, $commentId);
|
return $this->commentService->delete($cardId, $commentId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,20 +88,33 @@ class CommentService {
|
|||||||
* @param string $replyTo
|
* @param string $replyTo
|
||||||
* @return DataResponse
|
* @return DataResponse
|
||||||
* @throws BadRequestException
|
* @throws BadRequestException
|
||||||
* @throws NotFoundException
|
* @throws NotFoundException|NoPermissionException
|
||||||
*/
|
*/
|
||||||
public function create(string $cardId, string $message, string $replyTo = '0'): DataResponse {
|
public function create(string $cardId, string $message, string $replyTo = '0'): DataResponse {
|
||||||
if (!is_numeric($cardId)) {
|
if (!is_numeric($cardId)) {
|
||||||
throw new BadRequestException('A valid card id must be provided');
|
throw new BadRequestException('A valid card id must be provided');
|
||||||
}
|
}
|
||||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
$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 {
|
try {
|
||||||
$comment = $this->commentsManager->create('users', $this->userId, Application::COMMENT_ENTITY_TYPE, $cardId);
|
$comment = $this->commentsManager->create('users', $this->userId, Application::COMMENT_ENTITY_TYPE, $cardId);
|
||||||
$comment->setMessage($message);
|
$comment->setMessage($message);
|
||||||
$comment->setVerb('comment');
|
$comment->setVerb('comment');
|
||||||
$comment->setParentId($replyTo);
|
$comment->setParentId($replyTo);
|
||||||
$this->commentsManager->save($comment);
|
$this->commentsManager->save($comment);
|
||||||
return new DataResponse($this->formatComment($comment));
|
return new DataResponse($this->formatComment($comment, true));
|
||||||
} catch (\InvalidArgumentException $e) {
|
} catch (\InvalidArgumentException $e) {
|
||||||
throw new BadRequestException('Invalid input values');
|
throw new BadRequestException('Invalid input values');
|
||||||
} catch (MessageTooLongException $e) {
|
} catch (MessageTooLongException $e) {
|
||||||
@@ -122,12 +135,19 @@ class CommentService {
|
|||||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||||
try {
|
try {
|
||||||
$comment = $this->commentsManager->get($commentId);
|
$comment = $this->commentsManager->get($commentId);
|
||||||
|
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) {
|
||||||
|
throw new CommentNotFoundException();
|
||||||
|
}
|
||||||
} catch (CommentNotFoundException $e) {
|
} catch (CommentNotFoundException $e) {
|
||||||
throw new NotFoundException('No comment found.');
|
throw new NotFoundException('No comment found.');
|
||||||
}
|
}
|
||||||
if ($comment->getActorType() !== 'users' || $comment->getActorId() !== $this->userId) {
|
if ($comment->getActorType() !== 'users' || $comment->getActorId() !== $this->userId) {
|
||||||
throw new NoPermissionException('Only authors are allowed to edit their comment.');
|
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);
|
$comment->setMessage($message);
|
||||||
$this->commentsManager->save($comment);
|
$this->commentsManager->save($comment);
|
||||||
return new DataResponse($this->formatComment($comment));
|
return new DataResponse($this->formatComment($comment));
|
||||||
@@ -141,8 +161,12 @@ class CommentService {
|
|||||||
throw new BadRequestException('A valid comment id must be provided');
|
throw new BadRequestException('A valid comment id must be provided');
|
||||||
}
|
}
|
||||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$comment = $this->commentsManager->get($commentId);
|
$comment = $this->commentsManager->get($commentId);
|
||||||
|
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) {
|
||||||
|
throw new CommentNotFoundException();
|
||||||
|
}
|
||||||
} catch (CommentNotFoundException $e) {
|
} catch (CommentNotFoundException $e) {
|
||||||
throw new NotFoundException('No comment found.');
|
throw new NotFoundException('No comment found.');
|
||||||
}
|
}
|
||||||
@@ -153,13 +177,13 @@ class CommentService {
|
|||||||
return new DataResponse([]);
|
return new DataResponse([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function formatComment(IComment $comment): array {
|
private function formatComment(IComment $comment, $addReplyTo = false): array {
|
||||||
$user = $this->userManager->get($comment->getActorId());
|
$user = $this->userManager->get($comment->getActorId());
|
||||||
$actorDisplayName = $user !== null ? $user->getDisplayName() : $comment->getActorId();
|
$actorDisplayName = $user !== null ? $user->getDisplayName() : $comment->getActorId();
|
||||||
|
|
||||||
return [
|
$formattedComment = [
|
||||||
'id' => $comment->getId(),
|
'id' => (int)$comment->getId(),
|
||||||
'objectId' => $comment->getObjectId(),
|
'objectId' => (int)$comment->getObjectId(),
|
||||||
'message' => $comment->getMessage(),
|
'message' => $comment->getMessage(),
|
||||||
'actorId' => $comment->getActorId(),
|
'actorId' => $comment->getActorId(),
|
||||||
'actorType' => $comment->getActorType(),
|
'actorType' => $comment->getActorType(),
|
||||||
@@ -181,5 +205,13 @@ class CommentService {
|
|||||||
];
|
];
|
||||||
}, $comment->getMentions()),
|
}, $comment->getMentions()),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($addReplyTo && $comment->getParentId() !== '0' && $replyTo = $this->commentsManager->get($comment->getParentId())) {
|
||||||
|
$formattedComment['replyTo'] = $this->formatComment($replyTo);
|
||||||
|
}
|
||||||
|
} catch (CommentNotFoundException $e) {
|
||||||
|
}
|
||||||
|
return $formattedComment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export class CommentApi {
|
|||||||
|
|
||||||
async loadComments({ cardId, limit, offset }) {
|
async loadComments({ cardId, limit, offset }) {
|
||||||
const api = await axios.get(generateOcsUrl(`apps/deck/api/v1.0/cards`, 2) + `${cardId}/comments`, {
|
const api = await axios.get(generateOcsUrl(`apps/deck/api/v1.0/cards`, 2) + `${cardId}/comments`, {
|
||||||
|
params: { limit, offset },
|
||||||
headers: { 'OCS-APIRequest': 'true' },
|
headers: { 'OCS-APIRequest': 'true' },
|
||||||
})
|
})
|
||||||
return api.data.ocs.data
|
return api.data.ocs.data
|
||||||
|
|||||||
Reference in New Issue
Block a user