Show More
@@ -87,8 +87,9 b' class TestApi(object):' | |||
|
87 | 87 | id_, params = build_data(self.apikey, 'comment', args='xx') |
|
88 | 88 | response = api_call(self.app, params) |
|
89 | 89 | expected = 'No such method: comment. ' \ |
|
90 |
'Similar methods: changeset_comment, comment_pull_request, |
|
|
91 |
'get_pull_request_comments, comment_commit, |
|
|
90 | 'Similar methods: changeset_comment, comment_pull_request, ' \ | |
|
91 | 'get_pull_request_comments, comment_commit, edit_comment, ' \ | |
|
92 | 'get_comment, get_repo_comments' | |
|
92 | 93 | assert_error(id_, expected, given=response.body) |
|
93 | 94 | |
|
94 | 95 | def test_api_disabled_user(self, request): |
@@ -37,8 +37,10 b' class TestGetMethod(object):' | |||
|
37 | 37 | id_, params = build_data(self.apikey, 'get_method', pattern='*comment*') |
|
38 | 38 | response = api_call(self.app, params) |
|
39 | 39 | |
|
40 | expected = ['changeset_comment', 'comment_pull_request', 'edit_comment', | |
|
41 | 'get_pull_request_comments', 'comment_commit', 'get_repo_comments'] | |
|
40 | expected = [ | |
|
41 | 'changeset_comment', 'comment_pull_request', 'get_pull_request_comments', | |
|
42 | 'comment_commit', 'edit_comment', 'get_comment', 'get_repo_comments' | |
|
43 | ] | |
|
42 | 44 | assert_ok(id_, expected, given=response.body) |
|
43 | 45 | |
|
44 | 46 | def test_get_methods_on_single_match(self): |
@@ -61,6 +61,7 b' class TestGetPullRequestComments(object)' | |||
|
61 | 61 | 'comment_type': 'note', |
|
62 | 62 | 'comment_resolved_by': None, |
|
63 | 63 | 'pull_request_version': None, |
|
64 | 'comment_last_version': 0, | |
|
64 | 65 | 'comment_commit_id': None, |
|
65 | 66 | 'comment_pull_request_id': pull_request.pull_request_id |
|
66 | 67 | } |
@@ -42,26 +42,27 b' def make_repo_comments_factory(request):' | |||
|
42 | 42 | comments = [] |
|
43 | 43 | |
|
44 | 44 | # general |
|
45 | CommentsModel().create( | |
|
45 | comment = CommentsModel().create( | |
|
46 | 46 | text='General Comment', repo=repo, user=user, commit_id=commit_id, |
|
47 | 47 | comment_type=ChangesetComment.COMMENT_TYPE_NOTE, send_email=False) |
|
48 | comments.append(comment) | |
|
48 | 49 | |
|
49 | 50 | # inline |
|
50 | CommentsModel().create( | |
|
51 | comment = CommentsModel().create( | |
|
51 | 52 | text='Inline Comment', repo=repo, user=user, commit_id=commit_id, |
|
52 | 53 | f_path=file_0, line_no='n1', |
|
53 | 54 | comment_type=ChangesetComment.COMMENT_TYPE_NOTE, send_email=False) |
|
55 | comments.append(comment) | |
|
54 | 56 | |
|
55 | 57 | # todo |
|
56 | CommentsModel().create( | |
|
58 | comment = CommentsModel().create( | |
|
57 | 59 | text='INLINE TODO Comment', repo=repo, user=user, commit_id=commit_id, |
|
58 | 60 | f_path=file_0, line_no='n1', |
|
59 | 61 | comment_type=ChangesetComment.COMMENT_TYPE_TODO, send_email=False) |
|
62 | comments.append(comment) | |
|
60 | 63 | |
|
61 | @request.addfinalizer | |
|
62 | def cleanup(): | |
|
63 | for comment in comments: | |
|
64 | Session().delete(comment) | |
|
64 | return comments | |
|
65 | ||
|
65 | 66 | return Make() |
|
66 | 67 | |
|
67 | 68 | |
@@ -108,3 +109,34 b' class TestGetRepo(object):' | |||
|
108 | 109 | id_, params = build_data(self.apikey, 'get_repo_comments', **api_call_params) |
|
109 | 110 | response = api_call(self.app, params) |
|
110 | 111 | assert_error(id_, expected, given=response.body) |
|
112 | ||
|
113 | def test_api_get_comment(self, make_repo_comments_factory, backend_hg): | |
|
114 | commits = [{'message': 'A'}, {'message': 'B'}] | |
|
115 | repo = backend_hg.create_repo(commits=commits) | |
|
116 | ||
|
117 | comments = make_repo_comments_factory.make_comments(repo) | |
|
118 | comment_ids = [x.comment_id for x in comments] | |
|
119 | Session().commit() | |
|
120 | ||
|
121 | for comment_id in comment_ids: | |
|
122 | id_, params = build_data(self.apikey, 'get_comment', | |
|
123 | **{'comment_id': comment_id}) | |
|
124 | response = api_call(self.app, params) | |
|
125 | result = assert_call_ok(id_, given=response.body) | |
|
126 | assert result['comment_id'] == comment_id | |
|
127 | ||
|
128 | def test_api_get_comment_no_access(self, make_repo_comments_factory, backend_hg, user_util): | |
|
129 | commits = [{'message': 'A'}, {'message': 'B'}] | |
|
130 | repo = backend_hg.create_repo(commits=commits) | |
|
131 | comments = make_repo_comments_factory.make_comments(repo) | |
|
132 | comment_id = comments[0].comment_id | |
|
133 | ||
|
134 | test_user = user_util.create_user() | |
|
135 | user_util.grant_user_permission_to_repo(repo, test_user, 'repository.none') | |
|
136 | ||
|
137 | id_, params = build_data(test_user.api_key, 'get_comment', | |
|
138 | **{'comment_id': comment_id}) | |
|
139 | response = api_call(self.app, params) | |
|
140 | assert_error(id_, | |
|
141 | expected='comment `{}` does not exist'.format(comment_id), | |
|
142 | given=response.body) |
@@ -27,7 +27,6 b' from rhodecode.api.utils import (' | |||
|
27 | 27 | get_pull_request_or_error, get_commit_or_error, get_user_or_error, |
|
28 | 28 | validate_repo_permissions, resolve_ref_or_error, validate_set_owner_permissions) |
|
29 | 29 | from rhodecode.lib.auth import (HasRepoPermissionAnyApi) |
|
30 | from rhodecode.lib.exceptions import CommentVersionMismatch | |
|
31 | 30 | from rhodecode.lib.base import vcs_operation_context |
|
32 | 31 | from rhodecode.lib.utils2 import str2bool |
|
33 | 32 | from rhodecode.model.changeset_status import ChangesetStatusModel |
@@ -36,8 +35,7 b' from rhodecode.model.db import Session, ' | |||
|
36 | 35 | from rhodecode.model.pull_request import PullRequestModel, MergeCheck |
|
37 | 36 | from rhodecode.model.settings import SettingsModel |
|
38 | 37 | from rhodecode.model.validation_schema import Invalid |
|
39 |
from rhodecode.model.validation_schema.schemas.reviewer_schema import |
|
|
40 | ReviewerListSchema) | |
|
38 | from rhodecode.model.validation_schema.schemas.reviewer_schema import ReviewerListSchema | |
|
41 | 39 | |
|
42 | 40 | log = logging.getLogger(__name__) |
|
43 | 41 | |
@@ -380,6 +378,7 b' def get_pull_request_comments(' | |||
|
380 | 378 | }, |
|
381 | 379 | "comment_text": "Example text", |
|
382 | 380 | "comment_type": null, |
|
381 | "comment_last_version: 0, | |
|
383 | 382 | "pull_request_version": null, |
|
384 | 383 | "comment_commit_id": None, |
|
385 | 384 | "comment_pull_request_id": <pull_request_id> |
@@ -633,79 +632,6 b' def comment_pull_request(' | |||
|
633 | 632 | |
|
634 | 633 | |
|
635 | 634 | @jsonrpc_method() |
|
636 | def edit_comment( | |
|
637 | request, apiuser, message, comment_id, version, | |
|
638 | userid=Optional(OAttr('apiuser')), | |
|
639 | ): | |
|
640 | """ | |
|
641 | Edit comment on the pull request or commit, | |
|
642 | specified by the `comment_id` and version. Initially version should be 0 | |
|
643 | ||
|
644 | :param apiuser: This is filled automatically from the |authtoken|. | |
|
645 | :type apiuser: AuthUser | |
|
646 | :param comment_id: Specify the comment_id for editing | |
|
647 | :type comment_id: int | |
|
648 | :param version: version of the comment that will be created, starts from 0 | |
|
649 | :type version: int | |
|
650 | :param message: The text content of the comment. | |
|
651 | :type message: str | |
|
652 | :param userid: Comment on the pull request as this user | |
|
653 | :type userid: Optional(str or int) | |
|
654 | ||
|
655 | Example output: | |
|
656 | ||
|
657 | .. code-block:: bash | |
|
658 | ||
|
659 | id : <id_given_in_input> | |
|
660 | result : { | |
|
661 | "comment_history_id": "<Integer>", | |
|
662 | "version": "<Integer>", | |
|
663 | }, | |
|
664 | error : null | |
|
665 | """ | |
|
666 | ||
|
667 | auth_user = apiuser | |
|
668 | comment = ChangesetComment.get(comment_id) | |
|
669 | ||
|
670 | is_super_admin = has_superadmin_permission(apiuser) | |
|
671 | is_repo_admin = HasRepoPermissionAnyApi('repository.admin') \ | |
|
672 | (user=apiuser, repo_name=comment.repo.repo_name) | |
|
673 | ||
|
674 | if not isinstance(userid, Optional): | |
|
675 | if is_super_admin or is_repo_admin: | |
|
676 | apiuser = get_user_or_error(userid) | |
|
677 | auth_user = apiuser.AuthUser() | |
|
678 | else: | |
|
679 | raise JSONRPCError('userid is not the same as your user') | |
|
680 | ||
|
681 | comment_author = comment.author.user_id == auth_user.user_id | |
|
682 | if not (comment.immutable is False and (is_super_admin or is_repo_admin) or comment_author): | |
|
683 | raise JSONRPCError("you don't have access to edit this comment") | |
|
684 | ||
|
685 | try: | |
|
686 | comment_history = CommentsModel().edit( | |
|
687 | comment_id=comment_id, | |
|
688 | text=message, | |
|
689 | auth_user=auth_user, | |
|
690 | version=version, | |
|
691 | ) | |
|
692 | Session().commit() | |
|
693 | except CommentVersionMismatch: | |
|
694 | raise JSONRPCError( | |
|
695 | 'comment ({}) version ({}) mismatch'.format(comment_id, version) | |
|
696 | ) | |
|
697 | if not comment_history and not message: | |
|
698 | raise JSONRPCError( | |
|
699 | "comment ({}) can't be changed with empty string".format(comment_id) | |
|
700 | ) | |
|
701 | data = { | |
|
702 | 'comment_history_id': comment_history.comment_history_id if comment_history else None, | |
|
703 | 'version': comment_history.version if comment_history else None, | |
|
704 | } | |
|
705 | return data | |
|
706 | ||
|
707 | ||
|
708 | @jsonrpc_method() | |
|
709 | 635 | def create_pull_request( |
|
710 | 636 | request, apiuser, source_repo, target_repo, source_ref, target_ref, |
|
711 | 637 | owner=Optional(OAttr('apiuser')), title=Optional(''), description=Optional(''), |
@@ -31,11 +31,15 b' from rhodecode.api.utils import (' | |||
|
31 | 31 | validate_set_owner_permissions) |
|
32 | 32 | from rhodecode.lib import audit_logger, rc_cache |
|
33 | 33 | from rhodecode.lib import repo_maintenance |
|
34 | from rhodecode.lib.auth import HasPermissionAnyApi, HasUserGroupPermissionAnyApi | |
|
34 | from rhodecode.lib.auth import ( | |
|
35 | HasPermissionAnyApi, HasUserGroupPermissionAnyApi, | |
|
36 | HasRepoPermissionAnyApi) | |
|
35 | 37 | from rhodecode.lib.celerylib.utils import get_task_id |
|
36 | from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_str, safe_int, safe_unicode | |
|
38 | from rhodecode.lib.utils2 import ( | |
|
39 | str2bool, time_to_datetime, safe_str, safe_int, safe_unicode) | |
|
37 | 40 | from rhodecode.lib.ext_json import json |
|
38 |
from rhodecode.lib.exceptions import |
|
|
41 | from rhodecode.lib.exceptions import ( | |
|
42 | StatusChangeOnClosedPullRequestError, CommentVersionMismatch) | |
|
39 | 43 | from rhodecode.lib.vcs import RepositoryError |
|
40 | 44 | from rhodecode.lib.vcs.exceptions import NodeDoesNotExistError |
|
41 | 45 | from rhodecode.model.changeset_status import ChangesetStatusModel |
@@ -1719,7 +1723,8 b' def get_repo_comments(request, apiuser, ' | |||
|
1719 | 1723 | "comment_resolved_by": null, |
|
1720 | 1724 | "comment_status": [], |
|
1721 | 1725 | "comment_text": "This file needs a header", |
|
1722 | "comment_type": "todo" | |
|
1726 | "comment_type": "todo", | |
|
1727 | "comment_last_version: 0 | |
|
1723 | 1728 | } |
|
1724 | 1729 | ], |
|
1725 | 1730 | "error" : null |
@@ -1752,6 +1757,143 b' def get_repo_comments(request, apiuser, ' | |||
|
1752 | 1757 | |
|
1753 | 1758 | |
|
1754 | 1759 | @jsonrpc_method() |
|
1760 | def get_comment(request, apiuser, comment_id): | |
|
1761 | """ | |
|
1762 | Get single comment from repository or pull_request | |
|
1763 | ||
|
1764 | :param apiuser: This is filled automatically from the |authtoken|. | |
|
1765 | :type apiuser: AuthUser | |
|
1766 | :param comment_id: comment id found in the URL of comment | |
|
1767 | :type comment_id: str or int | |
|
1768 | ||
|
1769 | Example error output: | |
|
1770 | ||
|
1771 | .. code-block:: bash | |
|
1772 | ||
|
1773 | { | |
|
1774 | "id" : <id_given_in_input>, | |
|
1775 | "result" : { | |
|
1776 | "comment_author": <USER_DETAILS>, | |
|
1777 | "comment_created_on": "2017-02-01T14:38:16.309", | |
|
1778 | "comment_f_path": "file.txt", | |
|
1779 | "comment_id": 282, | |
|
1780 | "comment_lineno": "n1", | |
|
1781 | "comment_resolved_by": null, | |
|
1782 | "comment_status": [], | |
|
1783 | "comment_text": "This file needs a header", | |
|
1784 | "comment_type": "todo", | |
|
1785 | "comment_last_version: 0 | |
|
1786 | }, | |
|
1787 | "error" : null | |
|
1788 | } | |
|
1789 | ||
|
1790 | """ | |
|
1791 | ||
|
1792 | comment = ChangesetComment.get(comment_id) | |
|
1793 | if not comment: | |
|
1794 | raise JSONRPCError('comment `%s` does not exist' % (comment_id,)) | |
|
1795 | ||
|
1796 | perms = ('repository.read', 'repository.write', 'repository.admin') | |
|
1797 | has_comment_perm = HasRepoPermissionAnyApi(*perms)\ | |
|
1798 | (user=apiuser, repo_name=comment.repo.repo_name) | |
|
1799 | ||
|
1800 | if not has_comment_perm: | |
|
1801 | raise JSONRPCError('comment `%s` does not exist' % (comment_id,)) | |
|
1802 | ||
|
1803 | return comment | |
|
1804 | ||
|
1805 | ||
|
1806 | @jsonrpc_method() | |
|
1807 | def edit_comment(request, apiuser, message, comment_id, version, | |
|
1808 | userid=Optional(OAttr('apiuser'))): | |
|
1809 | """ | |
|
1810 | Edit comment on the pull request or commit, | |
|
1811 | specified by the `comment_id` and version. Initially version should be 0 | |
|
1812 | ||
|
1813 | :param apiuser: This is filled automatically from the |authtoken|. | |
|
1814 | :type apiuser: AuthUser | |
|
1815 | :param comment_id: Specify the comment_id for editing | |
|
1816 | :type comment_id: int | |
|
1817 | :param version: version of the comment that will be created, starts from 0 | |
|
1818 | :type version: int | |
|
1819 | :param message: The text content of the comment. | |
|
1820 | :type message: str | |
|
1821 | :param userid: Comment on the pull request as this user | |
|
1822 | :type userid: Optional(str or int) | |
|
1823 | ||
|
1824 | Example output: | |
|
1825 | ||
|
1826 | .. code-block:: bash | |
|
1827 | ||
|
1828 | id : <id_given_in_input> | |
|
1829 | result : { | |
|
1830 | "comment": "<comment data>", | |
|
1831 | "version": "<Integer>", | |
|
1832 | }, | |
|
1833 | error : null | |
|
1834 | """ | |
|
1835 | ||
|
1836 | auth_user = apiuser | |
|
1837 | comment = ChangesetComment.get(comment_id) | |
|
1838 | if not comment: | |
|
1839 | raise JSONRPCError('comment `%s` does not exist' % (comment_id,)) | |
|
1840 | ||
|
1841 | is_super_admin = has_superadmin_permission(apiuser) | |
|
1842 | is_repo_admin = HasRepoPermissionAnyApi('repository.admin')\ | |
|
1843 | (user=apiuser, repo_name=comment.repo.repo_name) | |
|
1844 | ||
|
1845 | if not isinstance(userid, Optional): | |
|
1846 | if is_super_admin or is_repo_admin: | |
|
1847 | apiuser = get_user_or_error(userid) | |
|
1848 | auth_user = apiuser.AuthUser() | |
|
1849 | else: | |
|
1850 | raise JSONRPCError('userid is not the same as your user') | |
|
1851 | ||
|
1852 | comment_author = comment.author.user_id == auth_user.user_id | |
|
1853 | if not (comment.immutable is False and (is_super_admin or is_repo_admin) or comment_author): | |
|
1854 | raise JSONRPCError("you don't have access to edit this comment") | |
|
1855 | ||
|
1856 | try: | |
|
1857 | comment_history = CommentsModel().edit( | |
|
1858 | comment_id=comment_id, | |
|
1859 | text=message, | |
|
1860 | auth_user=auth_user, | |
|
1861 | version=version, | |
|
1862 | ) | |
|
1863 | Session().commit() | |
|
1864 | except CommentVersionMismatch: | |
|
1865 | raise JSONRPCError( | |
|
1866 | 'comment ({}) version ({}) mismatch'.format(comment_id, version) | |
|
1867 | ) | |
|
1868 | if not comment_history and not message: | |
|
1869 | raise JSONRPCError( | |
|
1870 | "comment ({}) can't be changed with empty string".format(comment_id) | |
|
1871 | ) | |
|
1872 | data = { | |
|
1873 | 'comment': comment, | |
|
1874 | 'version': comment_history.version if comment_history else None, | |
|
1875 | } | |
|
1876 | return data | |
|
1877 | ||
|
1878 | ||
|
1879 | # TODO(marcink): write this with all required logic for deleting a comments in PR or commits | |
|
1880 | # @jsonrpc_method() | |
|
1881 | # def delete_comment(request, apiuser, comment_id): | |
|
1882 | # auth_user = apiuser | |
|
1883 | # | |
|
1884 | # comment = ChangesetComment.get(comment_id) | |
|
1885 | # if not comment: | |
|
1886 | # raise JSONRPCError('comment `%s` does not exist' % (comment_id,)) | |
|
1887 | # | |
|
1888 | # is_super_admin = has_superadmin_permission(apiuser) | |
|
1889 | # is_repo_admin = HasRepoPermissionAnyApi('repository.admin')\ | |
|
1890 | # (user=apiuser, repo_name=comment.repo.repo_name) | |
|
1891 | # | |
|
1892 | # comment_author = comment.author.user_id == auth_user.user_id | |
|
1893 | # if not (comment.immutable is False and (is_super_admin or is_repo_admin) or comment_author): | |
|
1894 | # raise JSONRPCError("you don't have access to edit this comment") | |
|
1895 | ||
|
1896 | @jsonrpc_method() | |
|
1755 | 1897 | def grant_user_permission(request, apiuser, repoid, userid, perm): |
|
1756 | 1898 | """ |
|
1757 | 1899 | Grant permissions for the specified user on the given repository, |
@@ -3845,6 +3845,13 b' class ChangesetComment(Base, BaseModel):' | |||
|
3845 | 3845 | def is_inline(self): |
|
3846 | 3846 | return self.line_no and self.f_path |
|
3847 | 3847 | |
|
3848 | @property | |
|
3849 | def last_version(self): | |
|
3850 | version = 0 | |
|
3851 | if self.history: | |
|
3852 | version = self.history[-1].version | |
|
3853 | return version | |
|
3854 | ||
|
3848 | 3855 | def get_index_version(self, versions): |
|
3849 | 3856 | return self.get_index_from_version( |
|
3850 | 3857 | self.pull_request_version_id, versions) |
@@ -3857,6 +3864,7 b' class ChangesetComment(Base, BaseModel):' | |||
|
3857 | 3864 | |
|
3858 | 3865 | def get_api_data(self): |
|
3859 | 3866 | comment = self |
|
3867 | ||
|
3860 | 3868 | data = { |
|
3861 | 3869 | 'comment_id': comment.comment_id, |
|
3862 | 3870 | 'comment_type': comment.comment_type, |
@@ -3869,6 +3877,7 b' class ChangesetComment(Base, BaseModel):' | |||
|
3869 | 3877 | 'comment_resolved_by': self.resolved, |
|
3870 | 3878 | 'comment_commit_id': comment.revision, |
|
3871 | 3879 | 'comment_pull_request_id': comment.pull_request_id, |
|
3880 | 'comment_last_version': self.last_version | |
|
3872 | 3881 | } |
|
3873 | 3882 | return data |
|
3874 | 3883 |
General Comments 0
You need to be logged in to leave comments.
Login now